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