1 | // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB |
2 | /* Copyright (c) 2015 - 2021 Intel Corporation */ |
3 | #include "main.h" |
4 | #include "i40iw_hw.h" |
5 | #include <linux/net/intel/i40e_client.h> |
6 | |
7 | static struct i40e_client i40iw_client; |
8 | |
9 | /** |
10 | * i40iw_l2param_change - handle mss change |
11 | * @cdev_info: parent lan device information structure with data/ops |
12 | * @client: client for parameter change |
13 | * @params: new parameters from L2 |
14 | */ |
15 | static void i40iw_l2param_change(struct i40e_info *cdev_info, |
16 | struct i40e_client *client, |
17 | struct i40e_params *params) |
18 | { |
19 | struct irdma_l2params l2params = {}; |
20 | struct irdma_device *iwdev; |
21 | struct ib_device *ibdev; |
22 | |
23 | ibdev = ib_device_get_by_netdev(ndev: cdev_info->netdev, driver_id: RDMA_DRIVER_IRDMA); |
24 | if (!ibdev) |
25 | return; |
26 | |
27 | iwdev = to_iwdev(ibdev); |
28 | |
29 | if (iwdev->vsi.mtu != params->mtu) { |
30 | l2params.mtu_changed = true; |
31 | l2params.mtu = params->mtu; |
32 | } |
33 | irdma_change_l2params(vsi: &iwdev->vsi, l2params: &l2params); |
34 | ib_device_put(device: ibdev); |
35 | } |
36 | |
37 | /** |
38 | * i40iw_close - client interface operation close for iwarp/uda device |
39 | * @cdev_info: parent lan device information structure with data/ops |
40 | * @client: client to close |
41 | * @reset: flag to indicate close on reset |
42 | * |
43 | * Called by the lan driver during the processing of client unregister |
44 | * Destroy and clean up the driver resources |
45 | */ |
46 | static void i40iw_close(struct i40e_info *cdev_info, struct i40e_client *client, |
47 | bool reset) |
48 | { |
49 | struct irdma_device *iwdev; |
50 | struct ib_device *ibdev; |
51 | |
52 | ibdev = ib_device_get_by_netdev(ndev: cdev_info->netdev, driver_id: RDMA_DRIVER_IRDMA); |
53 | if (WARN_ON(!ibdev)) |
54 | return; |
55 | |
56 | iwdev = to_iwdev(ibdev); |
57 | if (reset) |
58 | iwdev->rf->reset = true; |
59 | |
60 | iwdev->iw_status = 0; |
61 | irdma_port_ibevent(iwdev); |
62 | ib_unregister_device_and_put(device: ibdev); |
63 | pr_debug("INIT: Gen1 PF[%d] close complete\n" , PCI_FUNC(cdev_info->pcidev->devfn)); |
64 | } |
65 | |
66 | static void i40iw_request_reset(struct irdma_pci_f *rf) |
67 | { |
68 | struct i40e_info *cdev_info = rf->cdev; |
69 | |
70 | cdev_info->ops->request_reset(cdev_info, &i40iw_client, 1); |
71 | } |
72 | |
73 | static void i40iw_fill_device_info(struct irdma_device *iwdev, struct i40e_info *cdev_info) |
74 | { |
75 | struct irdma_pci_f *rf = iwdev->rf; |
76 | |
77 | rf->rdma_ver = IRDMA_GEN_1; |
78 | rf->gen_ops.request_reset = i40iw_request_reset; |
79 | rf->pcidev = cdev_info->pcidev; |
80 | rf->pf_id = cdev_info->fid; |
81 | rf->hw.hw_addr = cdev_info->hw_addr; |
82 | rf->cdev = cdev_info; |
83 | rf->msix_count = cdev_info->msix_count; |
84 | rf->msix_entries = cdev_info->msix_entries; |
85 | rf->limits_sel = 5; |
86 | rf->protocol_used = IRDMA_IWARP_PROTOCOL_ONLY; |
87 | rf->iwdev = iwdev; |
88 | |
89 | iwdev->init_state = INITIAL_STATE; |
90 | iwdev->rcv_wnd = IRDMA_CM_DEFAULT_RCV_WND_SCALED; |
91 | iwdev->rcv_wscale = IRDMA_CM_DEFAULT_RCV_WND_SCALE; |
92 | iwdev->netdev = cdev_info->netdev; |
93 | iwdev->vsi_num = 0; |
94 | } |
95 | |
96 | /** |
97 | * i40iw_open - client interface operation open for iwarp/uda device |
98 | * @cdev_info: parent lan device information structure with data/ops |
99 | * @client: iwarp client information, provided during registration |
100 | * |
101 | * Called by the lan driver during the processing of client register |
102 | * Create device resources, set up queues, pble and hmc objects and |
103 | * register the device with the ib verbs interface |
104 | * Return 0 if successful, otherwise return error |
105 | */ |
106 | static int i40iw_open(struct i40e_info *cdev_info, struct i40e_client *client) |
107 | { |
108 | struct irdma_l2params l2params = {}; |
109 | struct irdma_device *iwdev; |
110 | struct irdma_pci_f *rf; |
111 | int err = -EIO; |
112 | int i; |
113 | u16 qset; |
114 | u16 last_qset = IRDMA_NO_QSET; |
115 | |
116 | iwdev = ib_alloc_device(irdma_device, ibdev); |
117 | if (!iwdev) |
118 | return -ENOMEM; |
119 | |
120 | iwdev->rf = kzalloc(size: sizeof(*rf), GFP_KERNEL); |
121 | if (!iwdev->rf) { |
122 | ib_dealloc_device(device: &iwdev->ibdev); |
123 | return -ENOMEM; |
124 | } |
125 | |
126 | i40iw_fill_device_info(iwdev, cdev_info); |
127 | rf = iwdev->rf; |
128 | |
129 | if (irdma_ctrl_init_hw(rf)) { |
130 | err = -EIO; |
131 | goto err_ctrl_init; |
132 | } |
133 | |
134 | l2params.mtu = (cdev_info->params.mtu) ? cdev_info->params.mtu : IRDMA_DEFAULT_MTU; |
135 | for (i = 0; i < I40E_CLIENT_MAX_USER_PRIORITY; i++) { |
136 | qset = cdev_info->params.qos.prio_qos[i].qs_handle; |
137 | l2params.up2tc[i] = cdev_info->params.qos.prio_qos[i].tc; |
138 | l2params.qs_handle_list[i] = qset; |
139 | if (last_qset == IRDMA_NO_QSET) |
140 | last_qset = qset; |
141 | else if ((qset != last_qset) && (qset != IRDMA_NO_QSET)) |
142 | iwdev->dcb_vlan_mode = true; |
143 | } |
144 | |
145 | if (irdma_rt_init_hw(iwdev, l2params: &l2params)) { |
146 | err = -EIO; |
147 | goto err_rt_init; |
148 | } |
149 | |
150 | err = irdma_ib_register_device(iwdev); |
151 | if (err) |
152 | goto err_ibreg; |
153 | |
154 | ibdev_dbg(&iwdev->ibdev, "INIT: Gen1 PF[%d] open success\n" , |
155 | PCI_FUNC(rf->pcidev->devfn)); |
156 | |
157 | return 0; |
158 | |
159 | err_ibreg: |
160 | irdma_rt_deinit_hw(iwdev); |
161 | err_rt_init: |
162 | irdma_ctrl_deinit_hw(rf); |
163 | err_ctrl_init: |
164 | kfree(objp: iwdev->rf); |
165 | ib_dealloc_device(device: &iwdev->ibdev); |
166 | |
167 | return err; |
168 | } |
169 | |
170 | /* client interface functions */ |
171 | static const struct i40e_client_ops i40e_ops = { |
172 | .open = i40iw_open, |
173 | .close = i40iw_close, |
174 | .l2_param_change = i40iw_l2param_change |
175 | }; |
176 | |
177 | static struct i40e_client i40iw_client = { |
178 | .ops = &i40e_ops, |
179 | .type = I40E_CLIENT_IWARP, |
180 | }; |
181 | |
182 | static int i40iw_probe(struct auxiliary_device *aux_dev, const struct auxiliary_device_id *id) |
183 | { |
184 | struct i40e_auxiliary_device *i40e_adev = container_of(aux_dev, |
185 | struct i40e_auxiliary_device, |
186 | aux_dev); |
187 | struct i40e_info *cdev_info = i40e_adev->ldev; |
188 | |
189 | strscpy_pad(i40iw_client.name, "irdma" , I40E_CLIENT_STR_LENGTH); |
190 | i40e_client_device_register(ldev: cdev_info, client: &i40iw_client); |
191 | |
192 | return 0; |
193 | } |
194 | |
195 | static void i40iw_remove(struct auxiliary_device *aux_dev) |
196 | { |
197 | struct i40e_auxiliary_device *i40e_adev = container_of(aux_dev, |
198 | struct i40e_auxiliary_device, |
199 | aux_dev); |
200 | struct i40e_info *cdev_info = i40e_adev->ldev; |
201 | |
202 | i40e_client_device_unregister(ldev: cdev_info); |
203 | } |
204 | |
205 | static const struct auxiliary_device_id i40iw_auxiliary_id_table[] = { |
206 | {.name = "i40e.iwarp" , }, |
207 | {}, |
208 | }; |
209 | |
210 | MODULE_DEVICE_TABLE(auxiliary, i40iw_auxiliary_id_table); |
211 | |
212 | struct auxiliary_driver i40iw_auxiliary_drv = { |
213 | .name = "gen_1" , |
214 | .id_table = i40iw_auxiliary_id_table, |
215 | .probe = i40iw_probe, |
216 | .remove = i40iw_remove, |
217 | }; |
218 | |