xref: /linux/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c (revision 06d07429858317ded2db7986113a9e0129cd599b)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Marvell Octeon EP (EndPoint) Ethernet Driver
3  *
4  * Copyright (C) 2020 Marvell.
5  *
6  */
7 #include <linux/string.h>
8 #include <linux/types.h>
9 #include <linux/etherdevice.h>
10 #include <linux/pci.h>
11 #include <linux/wait.h>
12 
13 #include "octep_config.h"
14 #include "octep_main.h"
15 #include "octep_ctrl_net.h"
16 #include "octep_pfvf_mbox.h"
17 
18 /* Control plane version */
19 #define OCTEP_CP_VERSION_CURRENT	OCTEP_CP_VERSION(1, 0, 0)
20 
21 static const u32 req_hdr_sz = sizeof(union octep_ctrl_net_req_hdr);
22 static const u32 mtu_sz = sizeof(struct octep_ctrl_net_h2f_req_cmd_mtu);
23 static const u32 mac_sz = sizeof(struct octep_ctrl_net_h2f_req_cmd_mac);
24 static const u32 state_sz = sizeof(struct octep_ctrl_net_h2f_req_cmd_state);
25 static const u32 link_info_sz = sizeof(struct octep_ctrl_net_link_info);
26 static const u32 offloads_sz = sizeof(struct octep_ctrl_net_offloads);
27 static atomic_t ctrl_net_msg_id;
28 
29 /* Control plane version in which OCTEP_CTRL_NET_H2F_CMD was added */
30 static const u32 octep_ctrl_net_h2f_cmd_versions[OCTEP_CTRL_NET_H2F_CMD_MAX] = {
31 	[OCTEP_CTRL_NET_H2F_CMD_INVALID ... OCTEP_CTRL_NET_H2F_CMD_DEV_REMOVE] =
32 	 OCTEP_CP_VERSION(1, 0, 0),
33 	[OCTEP_CTRL_NET_H2F_CMD_OFFLOADS] = OCTEP_CP_VERSION(1, 0, 1)
34 
35 };
36 
37 /* Control plane version in which OCTEP_CTRL_NET_F2H_CMD was added */
38 static const u32 octep_ctrl_net_f2h_cmd_versions[OCTEP_CTRL_NET_F2H_CMD_MAX] = {
39 	[OCTEP_CTRL_NET_F2H_CMD_INVALID ... OCTEP_CTRL_NET_F2H_CMD_LINK_STATUS] =
40 	 OCTEP_CP_VERSION(1, 0, 0)
41 };
42 
init_send_req(struct octep_ctrl_mbox_msg * msg,void * buf,u16 sz,int vfid)43 static void init_send_req(struct octep_ctrl_mbox_msg *msg, void *buf,
44 			  u16 sz, int vfid)
45 {
46 	msg->hdr.s.flags = OCTEP_CTRL_MBOX_MSG_HDR_FLAG_REQ;
47 	msg->hdr.s.msg_id = atomic_inc_return(&ctrl_net_msg_id) &
48 			    GENMASK(sizeof(msg->hdr.s.msg_id) * BITS_PER_BYTE, 0);
49 	msg->hdr.s.sz = req_hdr_sz + sz;
50 	msg->sg_num = 1;
51 	msg->sg_list[0].msg = buf;
52 	msg->sg_list[0].sz = msg->hdr.s.sz;
53 	if (vfid != OCTEP_CTRL_NET_INVALID_VFID) {
54 		msg->hdr.s.is_vf = 1;
55 		msg->hdr.s.vf_idx = vfid;
56 	}
57 }
58 
octep_send_mbox_req(struct octep_device * oct,struct octep_ctrl_net_wait_data * d,bool wait_for_response)59 static int octep_send_mbox_req(struct octep_device *oct,
60 			       struct octep_ctrl_net_wait_data *d,
61 			       bool wait_for_response)
62 {
63 	int err, ret, cmd;
64 
65 	/* check if firmware is compatible for this request */
66 	cmd = d->data.req.hdr.s.cmd;
67 	if (octep_ctrl_net_h2f_cmd_versions[cmd] > oct->ctrl_mbox.max_fw_version ||
68 	    octep_ctrl_net_h2f_cmd_versions[cmd] < oct->ctrl_mbox.min_fw_version)
69 		return -EOPNOTSUPP;
70 
71 	err = octep_ctrl_mbox_send(&oct->ctrl_mbox, &d->msg);
72 	if (err < 0)
73 		return err;
74 
75 	if (!wait_for_response)
76 		return 0;
77 
78 	d->done = 0;
79 	INIT_LIST_HEAD(&d->list);
80 	list_add_tail(&d->list, &oct->ctrl_req_wait_list);
81 	ret = wait_event_interruptible_timeout(oct->ctrl_req_wait_q,
82 					       (d->done != 0),
83 					       msecs_to_jiffies(500));
84 	list_del(&d->list);
85 	if (ret == 0 || ret == 1)
86 		return -EAGAIN;
87 
88 	/**
89 	 * (ret == 0)  cond = false && timeout, return 0
90 	 * (ret < 0) interrupted by signal, return 0
91 	 * (ret == 1) cond = true && timeout, return 1
92 	 * (ret >= 1) cond = true && !timeout, return 1
93 	 */
94 
95 	if (d->data.resp.hdr.s.reply != OCTEP_CTRL_NET_REPLY_OK)
96 		return -EAGAIN;
97 
98 	return 0;
99 }
100 
octep_ctrl_net_init(struct octep_device * oct)101 int octep_ctrl_net_init(struct octep_device *oct)
102 {
103 	struct octep_ctrl_mbox *ctrl_mbox;
104 	struct pci_dev *pdev = oct->pdev;
105 	int ret;
106 
107 	init_waitqueue_head(&oct->ctrl_req_wait_q);
108 	INIT_LIST_HEAD(&oct->ctrl_req_wait_list);
109 
110 	/* Initialize control mbox */
111 	ctrl_mbox = &oct->ctrl_mbox;
112 	ctrl_mbox->version = OCTEP_CP_VERSION_CURRENT;
113 	ctrl_mbox->barmem = CFG_GET_CTRL_MBOX_MEM_ADDR(oct->conf);
114 	ret = octep_ctrl_mbox_init(ctrl_mbox);
115 	if (ret) {
116 		dev_err(&pdev->dev, "Failed to initialize control mbox\n");
117 		return ret;
118 	}
119 	dev_info(&pdev->dev, "Control plane versions host: %llx, firmware: %x:%x\n",
120 		 ctrl_mbox->version, ctrl_mbox->min_fw_version,
121 		 ctrl_mbox->max_fw_version);
122 	oct->ctrl_mbox_ifstats_offset = ctrl_mbox->barmem_sz;
123 
124 	return 0;
125 }
126 
octep_ctrl_net_get_link_status(struct octep_device * oct,int vfid)127 int octep_ctrl_net_get_link_status(struct octep_device *oct, int vfid)
128 {
129 	struct octep_ctrl_net_wait_data d = {};
130 	struct octep_ctrl_net_h2f_req *req = &d.data.req;
131 	int err;
132 
133 	init_send_req(&d.msg, (void *)req, state_sz, vfid);
134 	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_LINK_STATUS;
135 	req->link.cmd = OCTEP_CTRL_NET_CMD_GET;
136 	err = octep_send_mbox_req(oct, &d, true);
137 	if (err < 0)
138 		return err;
139 
140 	return d.data.resp.link.state;
141 }
142 
octep_ctrl_net_set_link_status(struct octep_device * oct,int vfid,bool up,bool wait_for_response)143 int octep_ctrl_net_set_link_status(struct octep_device *oct, int vfid, bool up,
144 				   bool wait_for_response)
145 {
146 	struct octep_ctrl_net_wait_data d = {};
147 	struct octep_ctrl_net_h2f_req *req = &d.data.req;
148 
149 	init_send_req(&d.msg, req, state_sz, vfid);
150 	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_LINK_STATUS;
151 	req->link.cmd = OCTEP_CTRL_NET_CMD_SET;
152 	req->link.state = (up) ? OCTEP_CTRL_NET_STATE_UP :
153 				OCTEP_CTRL_NET_STATE_DOWN;
154 
155 	return octep_send_mbox_req(oct, &d, wait_for_response);
156 }
157 
octep_ctrl_net_set_rx_state(struct octep_device * oct,int vfid,bool up,bool wait_for_response)158 int octep_ctrl_net_set_rx_state(struct octep_device *oct, int vfid, bool up,
159 				bool wait_for_response)
160 {
161 	struct octep_ctrl_net_wait_data d = {};
162 	struct octep_ctrl_net_h2f_req *req = &d.data.req;
163 
164 	init_send_req(&d.msg, req, state_sz, vfid);
165 	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_RX_STATE;
166 	req->link.cmd = OCTEP_CTRL_NET_CMD_SET;
167 	req->link.state = (up) ? OCTEP_CTRL_NET_STATE_UP :
168 				OCTEP_CTRL_NET_STATE_DOWN;
169 
170 	return octep_send_mbox_req(oct, &d, wait_for_response);
171 }
172 
octep_ctrl_net_get_mac_addr(struct octep_device * oct,int vfid,u8 * addr)173 int octep_ctrl_net_get_mac_addr(struct octep_device *oct, int vfid, u8 *addr)
174 {
175 	struct octep_ctrl_net_wait_data d = {};
176 	struct octep_ctrl_net_h2f_req *req = &d.data.req;
177 	int err;
178 
179 	init_send_req(&d.msg, req, mac_sz, vfid);
180 	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_MAC;
181 	req->link.cmd = OCTEP_CTRL_NET_CMD_GET;
182 	err = octep_send_mbox_req(oct, &d, true);
183 	if (err < 0)
184 		return err;
185 
186 	memcpy(addr, d.data.resp.mac.addr, ETH_ALEN);
187 
188 	return 0;
189 }
190 
octep_ctrl_net_set_mac_addr(struct octep_device * oct,int vfid,u8 * addr,bool wait_for_response)191 int octep_ctrl_net_set_mac_addr(struct octep_device *oct, int vfid, u8 *addr,
192 				bool wait_for_response)
193 {
194 	struct octep_ctrl_net_wait_data d = {};
195 	struct octep_ctrl_net_h2f_req *req = &d.data.req;
196 
197 	init_send_req(&d.msg, req, mac_sz, vfid);
198 	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_MAC;
199 	req->mac.cmd = OCTEP_CTRL_NET_CMD_SET;
200 	memcpy(&req->mac.addr, addr, ETH_ALEN);
201 
202 	return octep_send_mbox_req(oct, &d, wait_for_response);
203 }
204 
octep_ctrl_net_get_mtu(struct octep_device * oct,int vfid)205 int octep_ctrl_net_get_mtu(struct octep_device *oct, int vfid)
206 {
207 	struct octep_ctrl_net_wait_data d = {};
208 	struct octep_ctrl_net_h2f_req *req;
209 	int err;
210 
211 	req = &d.data.req;
212 	init_send_req(&d.msg, req, mtu_sz, vfid);
213 	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_MTU;
214 	req->mtu.cmd = OCTEP_CTRL_NET_CMD_GET;
215 
216 	err = octep_send_mbox_req(oct, &d, true);
217 	if (err < 0)
218 		return err;
219 
220 	return d.data.resp.mtu.val;
221 }
222 
octep_ctrl_net_set_mtu(struct octep_device * oct,int vfid,int mtu,bool wait_for_response)223 int octep_ctrl_net_set_mtu(struct octep_device *oct, int vfid, int mtu,
224 			   bool wait_for_response)
225 {
226 	struct octep_ctrl_net_wait_data d = {};
227 	struct octep_ctrl_net_h2f_req *req = &d.data.req;
228 
229 	init_send_req(&d.msg, req, mtu_sz, vfid);
230 	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_MTU;
231 	req->mtu.cmd = OCTEP_CTRL_NET_CMD_SET;
232 	req->mtu.val = mtu;
233 
234 	return octep_send_mbox_req(oct, &d, wait_for_response);
235 }
236 
octep_ctrl_net_get_if_stats(struct octep_device * oct,int vfid,struct octep_iface_rx_stats * rx_stats,struct octep_iface_tx_stats * tx_stats)237 int octep_ctrl_net_get_if_stats(struct octep_device *oct, int vfid,
238 				struct octep_iface_rx_stats *rx_stats,
239 				struct octep_iface_tx_stats *tx_stats)
240 {
241 	struct octep_ctrl_net_wait_data d = {};
242 	struct octep_ctrl_net_h2f_req *req = &d.data.req;
243 	struct octep_ctrl_net_h2f_resp *resp;
244 	int err;
245 
246 	init_send_req(&d.msg, req, 0, vfid);
247 	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_GET_IF_STATS;
248 	err = octep_send_mbox_req(oct, &d, true);
249 	if (err < 0)
250 		return err;
251 
252 	resp = &d.data.resp;
253 	memcpy(rx_stats, &resp->if_stats.rx_stats, sizeof(struct octep_iface_rx_stats));
254 	memcpy(tx_stats, &resp->if_stats.tx_stats, sizeof(struct octep_iface_tx_stats));
255 	return 0;
256 }
257 
octep_ctrl_net_get_link_info(struct octep_device * oct,int vfid,struct octep_iface_link_info * link_info)258 int octep_ctrl_net_get_link_info(struct octep_device *oct, int vfid,
259 				 struct octep_iface_link_info *link_info)
260 {
261 	struct octep_ctrl_net_wait_data d = {};
262 	struct octep_ctrl_net_h2f_req *req = &d.data.req;
263 	struct octep_ctrl_net_h2f_resp *resp;
264 	int err;
265 
266 	init_send_req(&d.msg, req, link_info_sz, vfid);
267 	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_LINK_INFO;
268 	req->link_info.cmd = OCTEP_CTRL_NET_CMD_GET;
269 	err = octep_send_mbox_req(oct, &d, true);
270 	if (err < 0)
271 		return err;
272 
273 	resp = &d.data.resp;
274 	link_info->supported_modes = resp->link_info.supported_modes;
275 	link_info->advertised_modes = resp->link_info.advertised_modes;
276 	link_info->autoneg = resp->link_info.autoneg;
277 	link_info->pause = resp->link_info.pause;
278 	link_info->speed = resp->link_info.speed;
279 
280 	return 0;
281 }
282 
octep_ctrl_net_set_link_info(struct octep_device * oct,int vfid,struct octep_iface_link_info * link_info,bool wait_for_response)283 int octep_ctrl_net_set_link_info(struct octep_device *oct, int vfid,
284 				 struct octep_iface_link_info *link_info,
285 				 bool wait_for_response)
286 {
287 	struct octep_ctrl_net_wait_data d = {};
288 	struct octep_ctrl_net_h2f_req *req = &d.data.req;
289 
290 	init_send_req(&d.msg, req, link_info_sz, vfid);
291 	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_LINK_INFO;
292 	req->link_info.cmd = OCTEP_CTRL_NET_CMD_SET;
293 	req->link_info.info.advertised_modes = link_info->advertised_modes;
294 	req->link_info.info.autoneg = link_info->autoneg;
295 	req->link_info.info.pause = link_info->pause;
296 	req->link_info.info.speed = link_info->speed;
297 
298 	return octep_send_mbox_req(oct, &d, wait_for_response);
299 }
300 
process_mbox_resp(struct octep_device * oct,struct octep_ctrl_mbox_msg * msg)301 static void process_mbox_resp(struct octep_device *oct,
302 			      struct octep_ctrl_mbox_msg *msg)
303 {
304 	struct octep_ctrl_net_wait_data *pos, *n;
305 
306 	list_for_each_entry_safe(pos, n, &oct->ctrl_req_wait_list, list) {
307 		if (pos->msg.hdr.s.msg_id == msg->hdr.s.msg_id) {
308 			memcpy(&pos->data.resp,
309 			       msg->sg_list[0].msg,
310 			       msg->hdr.s.sz);
311 			pos->done = 1;
312 			wake_up_interruptible_all(&oct->ctrl_req_wait_q);
313 			break;
314 		}
315 	}
316 }
317 
process_mbox_notify(struct octep_device * oct,struct octep_ctrl_mbox_msg * msg)318 static int process_mbox_notify(struct octep_device *oct,
319 			       struct octep_ctrl_mbox_msg *msg)
320 {
321 	struct net_device *netdev = oct->netdev;
322 	struct octep_ctrl_net_f2h_req *req;
323 	int cmd;
324 
325 	req = (struct octep_ctrl_net_f2h_req *)msg->sg_list[0].msg;
326 	cmd = req->hdr.s.cmd;
327 
328 	/* check if we support this command */
329 	if (octep_ctrl_net_f2h_cmd_versions[cmd] > OCTEP_CP_VERSION_CURRENT ||
330 	    octep_ctrl_net_f2h_cmd_versions[cmd] < OCTEP_CP_VERSION_CURRENT)
331 		return -EOPNOTSUPP;
332 
333 	if (msg->hdr.s.is_vf) {
334 		octep_pfvf_notify(oct, msg);
335 		return 0;
336 	}
337 
338 	switch (cmd) {
339 	case OCTEP_CTRL_NET_F2H_CMD_LINK_STATUS:
340 		if (netif_running(netdev)) {
341 			if (req->link.state) {
342 				dev_info(&oct->pdev->dev, "netif_carrier_on\n");
343 				netif_carrier_on(netdev);
344 			} else {
345 				dev_info(&oct->pdev->dev, "netif_carrier_off\n");
346 				netif_carrier_off(netdev);
347 			}
348 		}
349 		break;
350 	default:
351 		pr_info("Unknown mbox req : %u\n", req->hdr.s.cmd);
352 		break;
353 	}
354 
355 	return 0;
356 }
357 
octep_ctrl_net_recv_fw_messages(struct octep_device * oct)358 void octep_ctrl_net_recv_fw_messages(struct octep_device *oct)
359 {
360 	static u16 msg_sz = sizeof(union octep_ctrl_net_max_data);
361 	union octep_ctrl_net_max_data data = {};
362 	struct octep_ctrl_mbox_msg msg = {};
363 	int ret;
364 
365 	msg.hdr.s.sz = msg_sz;
366 	msg.sg_num = 1;
367 	msg.sg_list[0].sz = msg_sz;
368 	msg.sg_list[0].msg = &data;
369 	while (true) {
370 		/* mbox will overwrite msg.hdr.s.sz so initialize it */
371 		msg.hdr.s.sz = msg_sz;
372 		ret = octep_ctrl_mbox_recv(&oct->ctrl_mbox, (struct octep_ctrl_mbox_msg *)&msg);
373 		if (ret < 0)
374 			break;
375 
376 		if (msg.hdr.s.flags & OCTEP_CTRL_MBOX_MSG_HDR_FLAG_RESP)
377 			process_mbox_resp(oct, &msg);
378 		else if (msg.hdr.s.flags & OCTEP_CTRL_MBOX_MSG_HDR_FLAG_NOTIFY)
379 			process_mbox_notify(oct, &msg);
380 	}
381 }
382 
octep_ctrl_net_get_info(struct octep_device * oct,int vfid,struct octep_fw_info * info)383 int octep_ctrl_net_get_info(struct octep_device *oct, int vfid,
384 			    struct octep_fw_info *info)
385 {
386 	struct octep_ctrl_net_wait_data d = {};
387 	struct octep_ctrl_net_h2f_resp *resp;
388 	struct octep_ctrl_net_h2f_req *req;
389 	int err;
390 
391 	req = &d.data.req;
392 	init_send_req(&d.msg, req, 0, vfid);
393 	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_GET_INFO;
394 	req->link_info.cmd = OCTEP_CTRL_NET_CMD_GET;
395 	err = octep_send_mbox_req(oct, &d, true);
396 	if (err < 0)
397 		return err;
398 
399 	resp = &d.data.resp;
400 	memcpy(info, &resp->info.fw_info, sizeof(struct octep_fw_info));
401 
402 	return 0;
403 }
404 
octep_ctrl_net_dev_remove(struct octep_device * oct,int vfid)405 int octep_ctrl_net_dev_remove(struct octep_device *oct, int vfid)
406 {
407 	struct octep_ctrl_net_wait_data d = {};
408 	struct octep_ctrl_net_h2f_req *req;
409 
410 	req = &d.data.req;
411 	dev_dbg(&oct->pdev->dev, "Sending dev_unload msg to fw\n");
412 	init_send_req(&d.msg, req, sizeof(int), vfid);
413 	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_DEV_REMOVE;
414 
415 	return octep_send_mbox_req(oct, &d, false);
416 }
417 
octep_ctrl_net_set_offloads(struct octep_device * oct,int vfid,struct octep_ctrl_net_offloads * offloads,bool wait_for_response)418 int octep_ctrl_net_set_offloads(struct octep_device *oct, int vfid,
419 				struct octep_ctrl_net_offloads *offloads,
420 				bool wait_for_response)
421 {
422 	struct octep_ctrl_net_wait_data d = {};
423 	struct octep_ctrl_net_h2f_req *req;
424 
425 	req = &d.data.req;
426 	init_send_req(&d.msg, req, offloads_sz, vfid);
427 	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_OFFLOADS;
428 	req->offloads.cmd = OCTEP_CTRL_NET_CMD_SET;
429 	req->offloads.offloads = *offloads;
430 
431 	return octep_send_mbox_req(oct, &d, wait_for_response);
432 }
433 
octep_ctrl_net_uninit(struct octep_device * oct)434 int octep_ctrl_net_uninit(struct octep_device *oct)
435 {
436 	struct octep_ctrl_net_wait_data *pos, *n;
437 
438 	octep_ctrl_net_dev_remove(oct, OCTEP_CTRL_NET_INVALID_VFID);
439 
440 	list_for_each_entry_safe(pos, n, &oct->ctrl_req_wait_list, list)
441 		pos->done = 1;
442 
443 	wake_up_interruptible_all(&oct->ctrl_req_wait_q);
444 
445 	octep_ctrl_mbox_uninit(&oct->ctrl_mbox);
446 
447 	return 0;
448 }
449