| 1 | // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB |
| 2 | /* Copyright (c) 2015 - 2021 Intel Corporation */ |
| 3 | #include "main.h" |
| 4 | #include <linux/net/intel/iidc_rdma_idpf.h> |
| 5 | |
| 6 | MODULE_ALIAS("i40iw" ); |
| 7 | MODULE_DESCRIPTION("Intel(R) Ethernet Protocol Driver for RDMA" ); |
| 8 | MODULE_LICENSE("Dual BSD/GPL" ); |
| 9 | |
| 10 | static struct notifier_block irdma_inetaddr_notifier = { |
| 11 | .notifier_call = irdma_inetaddr_event |
| 12 | }; |
| 13 | |
| 14 | static struct notifier_block irdma_inetaddr6_notifier = { |
| 15 | .notifier_call = irdma_inet6addr_event |
| 16 | }; |
| 17 | |
| 18 | static struct notifier_block irdma_net_notifier = { |
| 19 | .notifier_call = irdma_net_event |
| 20 | }; |
| 21 | |
| 22 | static struct notifier_block irdma_netdevice_notifier = { |
| 23 | .notifier_call = irdma_netdevice_event |
| 24 | }; |
| 25 | |
| 26 | static void irdma_register_notifiers(void) |
| 27 | { |
| 28 | register_inetaddr_notifier(nb: &irdma_inetaddr_notifier); |
| 29 | register_inet6addr_notifier(nb: &irdma_inetaddr6_notifier); |
| 30 | register_netevent_notifier(nb: &irdma_net_notifier); |
| 31 | register_netdevice_notifier(nb: &irdma_netdevice_notifier); |
| 32 | } |
| 33 | |
| 34 | static void irdma_unregister_notifiers(void) |
| 35 | { |
| 36 | unregister_netevent_notifier(nb: &irdma_net_notifier); |
| 37 | unregister_inetaddr_notifier(nb: &irdma_inetaddr_notifier); |
| 38 | unregister_inet6addr_notifier(nb: &irdma_inetaddr6_notifier); |
| 39 | unregister_netdevice_notifier(nb: &irdma_netdevice_notifier); |
| 40 | } |
| 41 | |
| 42 | void irdma_log_invalid_mtu(u16 mtu, struct irdma_sc_dev *dev) |
| 43 | { |
| 44 | if (mtu < IRDMA_MIN_MTU_IPV4) |
| 45 | ibdev_warn(ibdev: to_ibdev(dev), format: "MTU setting [%d] too low for RDMA traffic. Minimum MTU is 576 for IPv4\n" , mtu); |
| 46 | else if (mtu < IRDMA_MIN_MTU_IPV6) |
| 47 | ibdev_warn(ibdev: to_ibdev(dev), format: "MTU setting [%d] too low for RDMA traffic. Minimum MTU is 1280 for IPv6\\n" , mtu); |
| 48 | } |
| 49 | |
| 50 | static void ig3rdma_idc_vport_event_handler(struct iidc_rdma_vport_dev_info *cdev_info, |
| 51 | struct iidc_rdma_event *event) |
| 52 | { |
| 53 | struct irdma_device *iwdev = auxiliary_get_drvdata(auxdev: cdev_info->adev); |
| 54 | struct irdma_l2params l2params = {}; |
| 55 | |
| 56 | if (*event->type & BIT(IIDC_RDMA_EVENT_AFTER_MTU_CHANGE)) { |
| 57 | ibdev_dbg(&iwdev->ibdev, "CLNT: new MTU = %d\n" , iwdev->netdev->mtu); |
| 58 | if (iwdev->vsi.mtu != iwdev->netdev->mtu) { |
| 59 | l2params.mtu = iwdev->netdev->mtu; |
| 60 | l2params.mtu_changed = true; |
| 61 | irdma_log_invalid_mtu(mtu: l2params.mtu, dev: &iwdev->rf->sc_dev); |
| 62 | irdma_change_l2params(vsi: &iwdev->vsi, l2params: &l2params); |
| 63 | } |
| 64 | } |
| 65 | } |
| 66 | |
| 67 | static int ig3rdma_vport_probe(struct auxiliary_device *aux_dev, |
| 68 | const struct auxiliary_device_id *id) |
| 69 | { |
| 70 | struct iidc_rdma_vport_auxiliary_dev *idc_adev = |
| 71 | container_of(aux_dev, struct iidc_rdma_vport_auxiliary_dev, adev); |
| 72 | struct auxiliary_device *aux_core_dev = idc_adev->vdev_info->core_adev; |
| 73 | struct irdma_pci_f *rf = auxiliary_get_drvdata(auxdev: aux_core_dev); |
| 74 | struct irdma_l2params l2params = {}; |
| 75 | struct irdma_device *iwdev; |
| 76 | int err; |
| 77 | |
| 78 | if (!rf) { |
| 79 | WARN_ON_ONCE(1); |
| 80 | return -ENOMEM; |
| 81 | } |
| 82 | iwdev = ib_alloc_device(irdma_device, ibdev); |
| 83 | /* Fill iwdev info */ |
| 84 | iwdev->is_vport = true; |
| 85 | iwdev->rf = rf; |
| 86 | iwdev->vport_id = idc_adev->vdev_info->vport_id; |
| 87 | iwdev->netdev = idc_adev->vdev_info->netdev; |
| 88 | iwdev->init_state = INITIAL_STATE; |
| 89 | iwdev->roce_cwnd = IRDMA_ROCE_CWND_DEFAULT; |
| 90 | iwdev->roce_ackcreds = IRDMA_ROCE_ACKCREDS_DEFAULT; |
| 91 | iwdev->rcv_wnd = IRDMA_CM_DEFAULT_RCV_WND_SCALED; |
| 92 | iwdev->rcv_wscale = IRDMA_CM_DEFAULT_RCV_WND_SCALE; |
| 93 | iwdev->roce_mode = true; |
| 94 | iwdev->push_mode = false; |
| 95 | |
| 96 | l2params.mtu = iwdev->netdev->mtu; |
| 97 | |
| 98 | err = irdma_rt_init_hw(iwdev, l2params: &l2params); |
| 99 | if (err) |
| 100 | goto err_rt_init; |
| 101 | |
| 102 | err = irdma_ib_register_device(iwdev); |
| 103 | if (err) |
| 104 | goto err_ibreg; |
| 105 | |
| 106 | auxiliary_set_drvdata(auxdev: aux_dev, data: iwdev); |
| 107 | |
| 108 | ibdev_dbg(&iwdev->ibdev, |
| 109 | "INIT: Gen[%d] vport[%d] probe success. dev_name = %s, core_dev_name = %s, netdev=%s\n" , |
| 110 | rf->rdma_ver, idc_adev->vdev_info->vport_id, |
| 111 | dev_name(&aux_dev->dev), |
| 112 | dev_name(&idc_adev->vdev_info->core_adev->dev), |
| 113 | netdev_name(idc_adev->vdev_info->netdev)); |
| 114 | |
| 115 | return 0; |
| 116 | err_ibreg: |
| 117 | irdma_rt_deinit_hw(iwdev); |
| 118 | err_rt_init: |
| 119 | ib_dealloc_device(device: &iwdev->ibdev); |
| 120 | |
| 121 | return err; |
| 122 | } |
| 123 | |
| 124 | static void ig3rdma_vport_remove(struct auxiliary_device *aux_dev) |
| 125 | { |
| 126 | struct iidc_rdma_vport_auxiliary_dev *idc_adev = |
| 127 | container_of(aux_dev, struct iidc_rdma_vport_auxiliary_dev, adev); |
| 128 | struct irdma_device *iwdev = auxiliary_get_drvdata(auxdev: aux_dev); |
| 129 | |
| 130 | ibdev_dbg(&iwdev->ibdev, |
| 131 | "INIT: Gen[%d] dev_name = %s, core_dev_name = %s, netdev=%s\n" , |
| 132 | iwdev->rf->rdma_ver, dev_name(&aux_dev->dev), |
| 133 | dev_name(&idc_adev->vdev_info->core_adev->dev), |
| 134 | netdev_name(idc_adev->vdev_info->netdev)); |
| 135 | |
| 136 | irdma_ib_unregister_device(iwdev); |
| 137 | } |
| 138 | |
| 139 | static const struct auxiliary_device_id ig3rdma_vport_auxiliary_id_table[] = { |
| 140 | {.name = "idpf.8086.rdma.vdev" , }, |
| 141 | {}, |
| 142 | }; |
| 143 | |
| 144 | MODULE_DEVICE_TABLE(auxiliary, ig3rdma_vport_auxiliary_id_table); |
| 145 | |
| 146 | static struct iidc_rdma_vport_auxiliary_drv ig3rdma_vport_auxiliary_drv = { |
| 147 | .adrv = { |
| 148 | .name = "vdev" , |
| 149 | .id_table = ig3rdma_vport_auxiliary_id_table, |
| 150 | .probe = ig3rdma_vport_probe, |
| 151 | .remove = ig3rdma_vport_remove, |
| 152 | }, |
| 153 | .event_handler = ig3rdma_idc_vport_event_handler, |
| 154 | }; |
| 155 | |
| 156 | |
| 157 | static int __init irdma_init_module(void) |
| 158 | { |
| 159 | int ret; |
| 160 | |
| 161 | ret = auxiliary_driver_register(&i40iw_auxiliary_drv); |
| 162 | if (ret) { |
| 163 | pr_err("Failed i40iw(gen_1) auxiliary_driver_register() ret=%d\n" , |
| 164 | ret); |
| 165 | return ret; |
| 166 | } |
| 167 | |
| 168 | ret = auxiliary_driver_register(&icrdma_core_auxiliary_drv.adrv); |
| 169 | if (ret) { |
| 170 | auxiliary_driver_unregister(auxdrv: &i40iw_auxiliary_drv); |
| 171 | pr_err("Failed icrdma(gen_2) auxiliary_driver_register() ret=%d\n" , |
| 172 | ret); |
| 173 | return ret; |
| 174 | } |
| 175 | |
| 176 | ret = auxiliary_driver_register(&ig3rdma_core_auxiliary_drv.adrv); |
| 177 | if (ret) { |
| 178 | auxiliary_driver_unregister(auxdrv: &icrdma_core_auxiliary_drv.adrv); |
| 179 | auxiliary_driver_unregister(auxdrv: &i40iw_auxiliary_drv); |
| 180 | pr_err("Failed ig3rdma(gen_3) core auxiliary_driver_register() ret=%d\n" , |
| 181 | ret); |
| 182 | |
| 183 | return ret; |
| 184 | } |
| 185 | |
| 186 | ret = auxiliary_driver_register(&ig3rdma_vport_auxiliary_drv.adrv); |
| 187 | if (ret) { |
| 188 | auxiliary_driver_unregister(auxdrv: &ig3rdma_core_auxiliary_drv.adrv); |
| 189 | auxiliary_driver_unregister(auxdrv: &icrdma_core_auxiliary_drv.adrv); |
| 190 | auxiliary_driver_unregister(auxdrv: &i40iw_auxiliary_drv); |
| 191 | pr_err("Failed ig3rdma vport auxiliary_driver_register() ret=%d\n" , |
| 192 | ret); |
| 193 | |
| 194 | return ret; |
| 195 | } |
| 196 | irdma_register_notifiers(); |
| 197 | |
| 198 | return 0; |
| 199 | } |
| 200 | |
| 201 | static void __exit irdma_exit_module(void) |
| 202 | { |
| 203 | irdma_unregister_notifiers(); |
| 204 | auxiliary_driver_unregister(auxdrv: &icrdma_core_auxiliary_drv.adrv); |
| 205 | auxiliary_driver_unregister(auxdrv: &i40iw_auxiliary_drv); |
| 206 | auxiliary_driver_unregister(auxdrv: &ig3rdma_core_auxiliary_drv.adrv); |
| 207 | auxiliary_driver_unregister(auxdrv: &ig3rdma_vport_auxiliary_drv.adrv); |
| 208 | } |
| 209 | |
| 210 | module_init(irdma_init_module); |
| 211 | module_exit(irdma_exit_module); |
| 212 | |