1 // SPDX-License-Identifier: GPL-2.0
2 /* Marvell Octeon EP (EndPoint) VF Ethernet Driver
3 *
4 * Copyright (C) 2020 Marvell.
5 *
6 */
7 #include <linux/types.h>
8 #include <linux/pci.h>
9 #include <linux/netdevice.h>
10 #include <linux/vmalloc.h>
11 #include "octep_vf_config.h"
12 #include "octep_vf_main.h"
13
14 /* When a new command is implemented, the below table should be updated
15 * with new command and it's version info.
16 */
17 static u32 pfvf_cmd_versions[OCTEP_PFVF_MBOX_CMD_MAX] = {
18 [0 ... OCTEP_PFVF_MBOX_CMD_DEV_REMOVE] = OCTEP_PFVF_MBOX_VERSION_V1,
19 [OCTEP_PFVF_MBOX_CMD_GET_FW_INFO ... OCTEP_PFVF_MBOX_NOTIF_LINK_STATUS] =
20 OCTEP_PFVF_MBOX_VERSION_V2
21 };
22
octep_vf_setup_mbox(struct octep_vf_device * oct)23 int octep_vf_setup_mbox(struct octep_vf_device *oct)
24 {
25 int ring = 0;
26
27 oct->mbox = vzalloc(sizeof(*oct->mbox));
28 if (!oct->mbox)
29 return -1;
30
31 mutex_init(&oct->mbox->lock);
32
33 oct->hw_ops.setup_mbox_regs(oct, ring);
34 INIT_WORK(&oct->mbox->wk.work, octep_vf_mbox_work);
35 oct->mbox->wk.ctxptr = oct;
36 oct->mbox_neg_ver = OCTEP_PFVF_MBOX_VERSION_CURRENT;
37 dev_info(&oct->pdev->dev, "setup vf mbox successfully\n");
38 return 0;
39 }
40
octep_vf_delete_mbox(struct octep_vf_device * oct)41 void octep_vf_delete_mbox(struct octep_vf_device *oct)
42 {
43 if (oct->mbox) {
44 if (work_pending(&oct->mbox->wk.work))
45 cancel_work_sync(&oct->mbox->wk.work);
46
47 mutex_destroy(&oct->mbox->lock);
48 vfree(oct->mbox);
49 oct->mbox = NULL;
50 dev_info(&oct->pdev->dev, "Deleted vf mbox successfully\n");
51 }
52 }
53
octep_vf_mbox_version_check(struct octep_vf_device * oct)54 int octep_vf_mbox_version_check(struct octep_vf_device *oct)
55 {
56 union octep_pfvf_mbox_word cmd;
57 union octep_pfvf_mbox_word rsp;
58 int ret;
59
60 cmd.u64 = 0;
61 cmd.s_version.opcode = OCTEP_PFVF_MBOX_CMD_VERSION;
62 cmd.s_version.version = OCTEP_PFVF_MBOX_VERSION_CURRENT;
63 ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp);
64 if (ret == OCTEP_PFVF_MBOX_CMD_STATUS_NACK) {
65 dev_err(&oct->pdev->dev,
66 "VF Mbox version is incompatible with PF\n");
67 return -EINVAL;
68 }
69 oct->mbox_neg_ver = (u32)rsp.s_version.version;
70 dev_dbg(&oct->pdev->dev,
71 "VF Mbox version:%u Negotiated VF version with PF:%u\n",
72 (u32)cmd.s_version.version,
73 (u32)rsp.s_version.version);
74 return 0;
75 }
76
octep_vf_mbox_work(struct work_struct * work)77 void octep_vf_mbox_work(struct work_struct *work)
78 {
79 struct octep_vf_mbox_wk *wk = container_of(work, struct octep_vf_mbox_wk, work);
80 struct octep_vf_iface_link_info *link_info;
81 struct octep_vf_device *oct = NULL;
82 struct octep_vf_mbox *mbox = NULL;
83 union octep_pfvf_mbox_word *notif;
84 u64 pf_vf_data;
85
86 oct = (struct octep_vf_device *)wk->ctxptr;
87 link_info = &oct->link_info;
88 mbox = oct->mbox;
89 pf_vf_data = readq(mbox->mbox_read_reg);
90
91 notif = (union octep_pfvf_mbox_word *)&pf_vf_data;
92
93 switch (notif->s.opcode) {
94 case OCTEP_PFVF_MBOX_NOTIF_LINK_STATUS:
95 if (notif->s_link_status.status) {
96 link_info->oper_up = OCTEP_PFVF_LINK_STATUS_UP;
97 netif_carrier_on(oct->netdev);
98 dev_info(&oct->pdev->dev, "netif_carrier_on\n");
99 } else {
100 link_info->oper_up = OCTEP_PFVF_LINK_STATUS_DOWN;
101 netif_carrier_off(oct->netdev);
102 dev_info(&oct->pdev->dev, "netif_carrier_off\n");
103 }
104 break;
105 default:
106 dev_err(&oct->pdev->dev,
107 "Received unsupported notif %d\n", notif->s.opcode);
108 break;
109 }
110 }
111
__octep_vf_mbox_send_cmd(struct octep_vf_device * oct,union octep_pfvf_mbox_word cmd,union octep_pfvf_mbox_word * rsp)112 static int __octep_vf_mbox_send_cmd(struct octep_vf_device *oct,
113 union octep_pfvf_mbox_word cmd,
114 union octep_pfvf_mbox_word *rsp)
115 {
116 struct octep_vf_mbox *mbox = oct->mbox;
117 u64 reg_val = 0ull;
118 int count;
119
120 if (!mbox)
121 return OCTEP_PFVF_MBOX_CMD_STATUS_NOT_SETUP;
122
123 cmd.s.type = OCTEP_PFVF_MBOX_TYPE_CMD;
124 writeq(cmd.u64, mbox->mbox_write_reg);
125
126 /* No response for notification messages */
127 if (!rsp)
128 return 0;
129
130 for (count = 0; count < OCTEP_PFVF_MBOX_TIMEOUT_WAIT_COUNT; count++) {
131 usleep_range(1000, 1500);
132 reg_val = readq(mbox->mbox_write_reg);
133 if (reg_val != cmd.u64) {
134 rsp->u64 = reg_val;
135 break;
136 }
137 }
138 if (count == OCTEP_PFVF_MBOX_TIMEOUT_WAIT_COUNT) {
139 dev_err(&oct->pdev->dev, "mbox send command timed out\n");
140 return OCTEP_PFVF_MBOX_CMD_STATUS_TIMEDOUT;
141 }
142 if (rsp->s.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) {
143 dev_err(&oct->pdev->dev, "mbox_send: Received NACK\n");
144 return OCTEP_PFVF_MBOX_CMD_STATUS_NACK;
145 }
146 rsp->u64 = reg_val;
147 return 0;
148 }
149
octep_vf_mbox_send_cmd(struct octep_vf_device * oct,union octep_pfvf_mbox_word cmd,union octep_pfvf_mbox_word * rsp)150 int octep_vf_mbox_send_cmd(struct octep_vf_device *oct, union octep_pfvf_mbox_word cmd,
151 union octep_pfvf_mbox_word *rsp)
152 {
153 struct octep_vf_mbox *mbox = oct->mbox;
154 int ret;
155
156 if (!mbox)
157 return OCTEP_PFVF_MBOX_CMD_STATUS_NOT_SETUP;
158 mutex_lock(&mbox->lock);
159 if (pfvf_cmd_versions[cmd.s.opcode] > oct->mbox_neg_ver) {
160 dev_dbg(&oct->pdev->dev, "CMD:%d not supported in Version:%d\n",
161 cmd.s.opcode, oct->mbox_neg_ver);
162 mutex_unlock(&mbox->lock);
163 return -EOPNOTSUPP;
164 }
165 ret = __octep_vf_mbox_send_cmd(oct, cmd, rsp);
166 mutex_unlock(&mbox->lock);
167 return ret;
168 }
169
octep_vf_mbox_bulk_read(struct octep_vf_device * oct,enum octep_pfvf_mbox_opcode opcode,u8 * data,int * size)170 int octep_vf_mbox_bulk_read(struct octep_vf_device *oct, enum octep_pfvf_mbox_opcode opcode,
171 u8 *data, int *size)
172 {
173 struct octep_vf_mbox *mbox = oct->mbox;
174 union octep_pfvf_mbox_word cmd;
175 union octep_pfvf_mbox_word rsp;
176 int data_len = 0, tmp_len = 0;
177 int read_cnt, i = 0, ret;
178
179 if (!mbox)
180 return OCTEP_PFVF_MBOX_CMD_STATUS_NOT_SETUP;
181
182 mutex_lock(&mbox->lock);
183 cmd.u64 = 0;
184 cmd.s_data.opcode = opcode;
185 cmd.s_data.frag = 0;
186 /* Send cmd to read data from PF */
187 ret = __octep_vf_mbox_send_cmd(oct, cmd, &rsp);
188 if (ret) {
189 dev_err(&oct->pdev->dev, "send mbox cmd fail for data request\n");
190 mutex_unlock(&mbox->lock);
191 return ret;
192 }
193 /* PF sends the data length of requested CMD
194 * in ACK
195 */
196 data_len = *((int32_t *)rsp.s_data.data);
197 tmp_len = data_len;
198 cmd.u64 = 0;
199 rsp.u64 = 0;
200 cmd.s_data.opcode = opcode;
201 cmd.s_data.frag = 1;
202 while (data_len) {
203 ret = __octep_vf_mbox_send_cmd(oct, cmd, &rsp);
204 if (ret) {
205 dev_err(&oct->pdev->dev, "send mbox cmd fail for data request\n");
206 mutex_unlock(&mbox->lock);
207 mbox->mbox_data.data_index = 0;
208 memset(mbox->mbox_data.recv_data, 0, OCTEP_PFVF_MBOX_MAX_DATA_BUF_SIZE);
209 return ret;
210 }
211 if (data_len > OCTEP_PFVF_MBOX_MAX_DATA_SIZE) {
212 data_len -= OCTEP_PFVF_MBOX_MAX_DATA_SIZE;
213 read_cnt = OCTEP_PFVF_MBOX_MAX_DATA_SIZE;
214 } else {
215 read_cnt = data_len;
216 data_len = 0;
217 }
218 for (i = 0; i < read_cnt; i++) {
219 mbox->mbox_data.recv_data[mbox->mbox_data.data_index] =
220 rsp.s_data.data[i];
221 mbox->mbox_data.data_index++;
222 }
223 cmd.u64 = 0;
224 rsp.u64 = 0;
225 cmd.s_data.opcode = opcode;
226 cmd.s_data.frag = 1;
227 }
228 memcpy(data, mbox->mbox_data.recv_data, tmp_len);
229 *size = tmp_len;
230 mbox->mbox_data.data_index = 0;
231 memset(mbox->mbox_data.recv_data, 0, OCTEP_PFVF_MBOX_MAX_DATA_BUF_SIZE);
232 mutex_unlock(&mbox->lock);
233 return 0;
234 }
235
octep_vf_mbox_set_mtu(struct octep_vf_device * oct,int mtu)236 int octep_vf_mbox_set_mtu(struct octep_vf_device *oct, int mtu)
237 {
238 int frame_size = mtu + ETH_HLEN + ETH_FCS_LEN;
239 union octep_pfvf_mbox_word cmd;
240 union octep_pfvf_mbox_word rsp;
241 int ret = 0;
242
243 if (mtu < ETH_MIN_MTU || frame_size > ETH_MAX_MTU) {
244 dev_err(&oct->pdev->dev,
245 "Failed to set MTU to %d MIN MTU:%d MAX MTU:%d\n",
246 mtu, ETH_MIN_MTU, ETH_MAX_MTU);
247 return -EINVAL;
248 }
249
250 cmd.u64 = 0;
251 cmd.s_set_mtu.opcode = OCTEP_PFVF_MBOX_CMD_SET_MTU;
252 cmd.s_set_mtu.mtu = mtu;
253
254 ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp);
255 if (ret) {
256 dev_err(&oct->pdev->dev, "Mbox send failed; err=%d\n", ret);
257 return ret;
258 }
259 if (rsp.s_set_mtu.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) {
260 dev_err(&oct->pdev->dev, "Received Mbox NACK from PF for MTU:%d\n", mtu);
261 return -EINVAL;
262 }
263
264 return 0;
265 }
266
octep_vf_mbox_set_mac_addr(struct octep_vf_device * oct,char * mac_addr)267 int octep_vf_mbox_set_mac_addr(struct octep_vf_device *oct, char *mac_addr)
268 {
269 union octep_pfvf_mbox_word cmd;
270 union octep_pfvf_mbox_word rsp;
271 int i, ret;
272
273 cmd.u64 = 0;
274 cmd.s_set_mac.opcode = OCTEP_PFVF_MBOX_CMD_SET_MAC_ADDR;
275 for (i = 0; i < ETH_ALEN; i++)
276 cmd.s_set_mac.mac_addr[i] = mac_addr[i];
277 ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp);
278 if (ret) {
279 dev_err(&oct->pdev->dev, "Mbox send failed; err = %d\n", ret);
280 return ret;
281 }
282 if (rsp.s_set_mac.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) {
283 dev_err(&oct->pdev->dev, "received NACK\n");
284 return -EINVAL;
285 }
286 return 0;
287 }
288
octep_vf_mbox_get_mac_addr(struct octep_vf_device * oct,char * mac_addr)289 int octep_vf_mbox_get_mac_addr(struct octep_vf_device *oct, char *mac_addr)
290 {
291 union octep_pfvf_mbox_word cmd;
292 union octep_pfvf_mbox_word rsp;
293 int i, ret;
294
295 cmd.u64 = 0;
296 cmd.s_set_mac.opcode = OCTEP_PFVF_MBOX_CMD_GET_MAC_ADDR;
297 ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp);
298 if (ret) {
299 dev_err(&oct->pdev->dev, "get_mac: mbox send failed; err = %d\n", ret);
300 return ret;
301 }
302 if (rsp.s_set_mac.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) {
303 dev_err(&oct->pdev->dev, "get_mac: received NACK\n");
304 return -EINVAL;
305 }
306 for (i = 0; i < ETH_ALEN; i++)
307 mac_addr[i] = rsp.s_set_mac.mac_addr[i];
308 return 0;
309 }
310
octep_vf_mbox_set_rx_state(struct octep_vf_device * oct,bool state)311 int octep_vf_mbox_set_rx_state(struct octep_vf_device *oct, bool state)
312 {
313 union octep_pfvf_mbox_word cmd;
314 union octep_pfvf_mbox_word rsp;
315 int ret;
316
317 cmd.u64 = 0;
318 cmd.s_link_state.opcode = OCTEP_PFVF_MBOX_CMD_SET_RX_STATE;
319 cmd.s_link_state.state = state;
320 ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp);
321 if (ret) {
322 dev_err(&oct->pdev->dev, "Set Rx state via VF Mbox send failed\n");
323 return ret;
324 }
325 if (rsp.s_link_state.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) {
326 dev_err(&oct->pdev->dev, "Set Rx state received NACK\n");
327 return -EINVAL;
328 }
329 return 0;
330 }
331
octep_vf_mbox_set_link_status(struct octep_vf_device * oct,bool status)332 int octep_vf_mbox_set_link_status(struct octep_vf_device *oct, bool status)
333 {
334 union octep_pfvf_mbox_word cmd;
335 union octep_pfvf_mbox_word rsp;
336 int ret;
337
338 cmd.u64 = 0;
339 cmd.s_link_status.opcode = OCTEP_PFVF_MBOX_CMD_SET_LINK_STATUS;
340 cmd.s_link_status.status = status;
341 ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp);
342 if (ret) {
343 dev_err(&oct->pdev->dev, "Set link status via VF Mbox send failed\n");
344 return ret;
345 }
346 if (rsp.s_link_status.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) {
347 dev_err(&oct->pdev->dev, "Set link status received NACK\n");
348 return -EINVAL;
349 }
350 return 0;
351 }
352
octep_vf_mbox_get_link_status(struct octep_vf_device * oct,u8 * oper_up)353 int octep_vf_mbox_get_link_status(struct octep_vf_device *oct, u8 *oper_up)
354 {
355 union octep_pfvf_mbox_word cmd;
356 union octep_pfvf_mbox_word rsp;
357 int ret;
358
359 cmd.u64 = 0;
360 cmd.s_link_status.opcode = OCTEP_PFVF_MBOX_CMD_GET_LINK_STATUS;
361 ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp);
362 if (ret) {
363 dev_err(&oct->pdev->dev, "Get link status via VF Mbox send failed\n");
364 return ret;
365 }
366 if (rsp.s_link_status.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) {
367 dev_err(&oct->pdev->dev, "Get link status received NACK\n");
368 return -EINVAL;
369 }
370 *oper_up = rsp.s_link_status.status;
371 return 0;
372 }
373
octep_vf_mbox_dev_remove(struct octep_vf_device * oct)374 int octep_vf_mbox_dev_remove(struct octep_vf_device *oct)
375 {
376 union octep_pfvf_mbox_word cmd;
377 int ret;
378
379 cmd.u64 = 0;
380 cmd.s.opcode = OCTEP_PFVF_MBOX_CMD_DEV_REMOVE;
381 ret = octep_vf_mbox_send_cmd(oct, cmd, NULL);
382 return ret;
383 }
384
octep_vf_mbox_get_fw_info(struct octep_vf_device * oct)385 int octep_vf_mbox_get_fw_info(struct octep_vf_device *oct)
386 {
387 union octep_pfvf_mbox_word cmd;
388 union octep_pfvf_mbox_word rsp;
389 int ret;
390
391 cmd.u64 = 0;
392 cmd.s_fw_info.opcode = OCTEP_PFVF_MBOX_CMD_GET_FW_INFO;
393 ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp);
394 if (ret) {
395 dev_err(&oct->pdev->dev, "Get link status via VF Mbox send failed\n");
396 return ret;
397 }
398 if (rsp.s_fw_info.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) {
399 dev_err(&oct->pdev->dev, "Get link status received NACK\n");
400 return -EINVAL;
401 }
402 oct->fw_info.pkind = rsp.s_fw_info.pkind;
403 oct->fw_info.fsz = rsp.s_fw_info.fsz;
404 oct->fw_info.rx_ol_flags = rsp.s_fw_info.rx_ol_flags;
405 oct->fw_info.tx_ol_flags = rsp.s_fw_info.tx_ol_flags;
406
407 return 0;
408 }
409
octep_vf_mbox_set_offloads(struct octep_vf_device * oct,u16 tx_offloads,u16 rx_offloads)410 int octep_vf_mbox_set_offloads(struct octep_vf_device *oct, u16 tx_offloads,
411 u16 rx_offloads)
412 {
413 union octep_pfvf_mbox_word cmd;
414 union octep_pfvf_mbox_word rsp;
415 int ret;
416
417 cmd.u64 = 0;
418 cmd.s_offloads.opcode = OCTEP_PFVF_MBOX_CMD_SET_OFFLOADS;
419 cmd.s_offloads.rx_ol_flags = rx_offloads;
420 cmd.s_offloads.tx_ol_flags = tx_offloads;
421 ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp);
422 if (ret) {
423 dev_err(&oct->pdev->dev, "Set offloads via VF Mbox send failed\n");
424 return ret;
425 }
426 if (rsp.s_link_state.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) {
427 dev_err(&oct->pdev->dev, "Set offloads received NACK\n");
428 return -EINVAL;
429 }
430 return 0;
431 }
432