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 
17 /* Control plane version */
18 #define OCTEP_CP_VERSION_CURRENT	OCTEP_CP_VERSION(1, 0, 0)
19 
20 static const u32 req_hdr_sz = sizeof(union octep_ctrl_net_req_hdr);
21 static const u32 mtu_sz = sizeof(struct octep_ctrl_net_h2f_req_cmd_mtu);
22 static const u32 mac_sz = sizeof(struct octep_ctrl_net_h2f_req_cmd_mac);
23 static const u32 state_sz = sizeof(struct octep_ctrl_net_h2f_req_cmd_state);
24 static const u32 link_info_sz = sizeof(struct octep_ctrl_net_link_info);
25 static atomic_t ctrl_net_msg_id;
26 
27 /* Control plane version in which OCTEP_CTRL_NET_H2F_CMD was added */
28 static const u32 octep_ctrl_net_h2f_cmd_versions[OCTEP_CTRL_NET_H2F_CMD_MAX] = {
29 	[OCTEP_CTRL_NET_H2F_CMD_INVALID ... OCTEP_CTRL_NET_H2F_CMD_LINK_INFO] =
30 	 OCTEP_CP_VERSION(1, 0, 0)
31 };
32 
33 /* Control plane version in which OCTEP_CTRL_NET_F2H_CMD was added */
34 static const u32 octep_ctrl_net_f2h_cmd_versions[OCTEP_CTRL_NET_F2H_CMD_MAX] = {
35 	[OCTEP_CTRL_NET_F2H_CMD_INVALID ... OCTEP_CTRL_NET_F2H_CMD_LINK_STATUS] =
36 	 OCTEP_CP_VERSION(1, 0, 0)
37 };
38 
init_send_req(struct octep_ctrl_mbox_msg * msg,void * buf,u16 sz,int vfid)39 static void init_send_req(struct octep_ctrl_mbox_msg *msg, void *buf,
40 			  u16 sz, int vfid)
41 {
42 	msg->hdr.s.flags = OCTEP_CTRL_MBOX_MSG_HDR_FLAG_REQ;
43 	msg->hdr.s.msg_id = atomic_inc_return(&ctrl_net_msg_id) &
44 			    GENMASK(sizeof(msg->hdr.s.msg_id) * BITS_PER_BYTE, 0);
45 	msg->hdr.s.sz = req_hdr_sz + sz;
46 	msg->sg_num = 1;
47 	msg->sg_list[0].msg = buf;
48 	msg->sg_list[0].sz = msg->hdr.s.sz;
49 	if (vfid != OCTEP_CTRL_NET_INVALID_VFID) {
50 		msg->hdr.s.is_vf = 1;
51 		msg->hdr.s.vf_idx = vfid;
52 	}
53 }
54 
octep_send_mbox_req(struct octep_device * oct,struct octep_ctrl_net_wait_data * d,bool wait_for_response)55 static int octep_send_mbox_req(struct octep_device *oct,
56 			       struct octep_ctrl_net_wait_data *d,
57 			       bool wait_for_response)
58 {
59 	int err, ret, cmd;
60 
61 	/* check if firmware is compatible for this request */
62 	cmd = d->data.req.hdr.s.cmd;
63 	if (octep_ctrl_net_h2f_cmd_versions[cmd] > oct->ctrl_mbox.max_fw_version ||
64 	    octep_ctrl_net_h2f_cmd_versions[cmd] < oct->ctrl_mbox.min_fw_version)
65 		return -EOPNOTSUPP;
66 
67 	err = octep_ctrl_mbox_send(&oct->ctrl_mbox, &d->msg);
68 	if (err < 0)
69 		return err;
70 
71 	if (!wait_for_response)
72 		return 0;
73 
74 	d->done = 0;
75 	INIT_LIST_HEAD(&d->list);
76 	list_add_tail(&d->list, &oct->ctrl_req_wait_list);
77 	ret = wait_event_interruptible_timeout(oct->ctrl_req_wait_q,
78 					       (d->done != 0),
79 					       msecs_to_jiffies(500));
80 	list_del(&d->list);
81 	if (ret == 0 || ret == 1)
82 		return -EAGAIN;
83 
84 	/**
85 	 * (ret == 0)  cond = false && timeout, return 0
86 	 * (ret < 0) interrupted by signal, return 0
87 	 * (ret == 1) cond = true && timeout, return 1
88 	 * (ret >= 1) cond = true && !timeout, return 1
89 	 */
90 
91 	if (d->data.resp.hdr.s.reply != OCTEP_CTRL_NET_REPLY_OK)
92 		return -EAGAIN;
93 
94 	return 0;
95 }
96 
octep_ctrl_net_init(struct octep_device * oct)97 int octep_ctrl_net_init(struct octep_device *oct)
98 {
99 	struct octep_ctrl_mbox *ctrl_mbox;
100 	struct pci_dev *pdev = oct->pdev;
101 	int ret;
102 
103 	init_waitqueue_head(&oct->ctrl_req_wait_q);
104 	INIT_LIST_HEAD(&oct->ctrl_req_wait_list);
105 
106 	/* Initialize control mbox */
107 	ctrl_mbox = &oct->ctrl_mbox;
108 	ctrl_mbox->version = OCTEP_CP_VERSION_CURRENT;
109 	ctrl_mbox->barmem = CFG_GET_CTRL_MBOX_MEM_ADDR(oct->conf);
110 	ret = octep_ctrl_mbox_init(ctrl_mbox);
111 	if (ret) {
112 		dev_err(&pdev->dev, "Failed to initialize control mbox\n");
113 		return ret;
114 	}
115 	dev_info(&pdev->dev, "Control plane versions host: %llx, firmware: %x:%x\n",
116 		 ctrl_mbox->version, ctrl_mbox->min_fw_version,
117 		 ctrl_mbox->max_fw_version);
118 	oct->ctrl_mbox_ifstats_offset = ctrl_mbox->barmem_sz;
119 
120 	return 0;
121 }
122 
octep_ctrl_net_get_link_status(struct octep_device * oct,int vfid)123 int octep_ctrl_net_get_link_status(struct octep_device *oct, int vfid)
124 {
125 	struct octep_ctrl_net_wait_data d = {0};
126 	struct octep_ctrl_net_h2f_req *req = &d.data.req;
127 	int err;
128 
129 	init_send_req(&d.msg, (void *)req, state_sz, vfid);
130 	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_LINK_STATUS;
131 	req->link.cmd = OCTEP_CTRL_NET_CMD_GET;
132 	err = octep_send_mbox_req(oct, &d, true);
133 	if (err < 0)
134 		return err;
135 
136 	return d.data.resp.link.state;
137 }
138 
octep_ctrl_net_set_link_status(struct octep_device * oct,int vfid,bool up,bool wait_for_response)139 int octep_ctrl_net_set_link_status(struct octep_device *oct, int vfid, bool up,
140 				   bool wait_for_response)
141 {
142 	struct octep_ctrl_net_wait_data d = {0};
143 	struct octep_ctrl_net_h2f_req *req = &d.data.req;
144 
145 	init_send_req(&d.msg, req, state_sz, vfid);
146 	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_LINK_STATUS;
147 	req->link.cmd = OCTEP_CTRL_NET_CMD_SET;
148 	req->link.state = (up) ? OCTEP_CTRL_NET_STATE_UP :
149 				OCTEP_CTRL_NET_STATE_DOWN;
150 
151 	return octep_send_mbox_req(oct, &d, wait_for_response);
152 }
153 
octep_ctrl_net_set_rx_state(struct octep_device * oct,int vfid,bool up,bool wait_for_response)154 int octep_ctrl_net_set_rx_state(struct octep_device *oct, int vfid, bool up,
155 				bool wait_for_response)
156 {
157 	struct octep_ctrl_net_wait_data d = {0};
158 	struct octep_ctrl_net_h2f_req *req = &d.data.req;
159 
160 	init_send_req(&d.msg, req, state_sz, vfid);
161 	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_RX_STATE;
162 	req->link.cmd = OCTEP_CTRL_NET_CMD_SET;
163 	req->link.state = (up) ? OCTEP_CTRL_NET_STATE_UP :
164 				OCTEP_CTRL_NET_STATE_DOWN;
165 
166 	return octep_send_mbox_req(oct, &d, wait_for_response);
167 }
168 
octep_ctrl_net_get_mac_addr(struct octep_device * oct,int vfid,u8 * addr)169 int octep_ctrl_net_get_mac_addr(struct octep_device *oct, int vfid, u8 *addr)
170 {
171 	struct octep_ctrl_net_wait_data d = {0};
172 	struct octep_ctrl_net_h2f_req *req = &d.data.req;
173 	int err;
174 
175 	init_send_req(&d.msg, req, mac_sz, vfid);
176 	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_MAC;
177 	req->link.cmd = OCTEP_CTRL_NET_CMD_GET;
178 	err = octep_send_mbox_req(oct, &d, true);
179 	if (err < 0)
180 		return err;
181 
182 	memcpy(addr, d.data.resp.mac.addr, ETH_ALEN);
183 
184 	return 0;
185 }
186 
octep_ctrl_net_set_mac_addr(struct octep_device * oct,int vfid,u8 * addr,bool wait_for_response)187 int octep_ctrl_net_set_mac_addr(struct octep_device *oct, int vfid, u8 *addr,
188 				bool wait_for_response)
189 {
190 	struct octep_ctrl_net_wait_data d = {0};
191 	struct octep_ctrl_net_h2f_req *req = &d.data.req;
192 
193 	init_send_req(&d.msg, req, mac_sz, vfid);
194 	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_MAC;
195 	req->mac.cmd = OCTEP_CTRL_NET_CMD_SET;
196 	memcpy(&req->mac.addr, addr, ETH_ALEN);
197 
198 	return octep_send_mbox_req(oct, &d, wait_for_response);
199 }
200 
octep_ctrl_net_set_mtu(struct octep_device * oct,int vfid,int mtu,bool wait_for_response)201 int octep_ctrl_net_set_mtu(struct octep_device *oct, int vfid, int mtu,
202 			   bool wait_for_response)
203 {
204 	struct octep_ctrl_net_wait_data d = {0};
205 	struct octep_ctrl_net_h2f_req *req = &d.data.req;
206 
207 	init_send_req(&d.msg, req, mtu_sz, vfid);
208 	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_MTU;
209 	req->mtu.cmd = OCTEP_CTRL_NET_CMD_SET;
210 	req->mtu.val = mtu;
211 
212 	return octep_send_mbox_req(oct, &d, wait_for_response);
213 }
214 
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)215 int octep_ctrl_net_get_if_stats(struct octep_device *oct, int vfid,
216 				struct octep_iface_rx_stats *rx_stats,
217 				struct octep_iface_tx_stats *tx_stats)
218 {
219 	struct octep_ctrl_net_wait_data d = {0};
220 	struct octep_ctrl_net_h2f_req *req = &d.data.req;
221 	struct octep_ctrl_net_h2f_resp *resp;
222 	int err;
223 
224 	init_send_req(&d.msg, req, 0, vfid);
225 	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_GET_IF_STATS;
226 	err = octep_send_mbox_req(oct, &d, true);
227 	if (err < 0)
228 		return err;
229 
230 	resp = &d.data.resp;
231 	memcpy(rx_stats, &resp->if_stats.rx_stats, sizeof(struct octep_iface_rx_stats));
232 	memcpy(tx_stats, &resp->if_stats.tx_stats, sizeof(struct octep_iface_tx_stats));
233 	return 0;
234 }
235 
octep_ctrl_net_get_link_info(struct octep_device * oct,int vfid,struct octep_iface_link_info * link_info)236 int octep_ctrl_net_get_link_info(struct octep_device *oct, int vfid,
237 				 struct octep_iface_link_info *link_info)
238 {
239 	struct octep_ctrl_net_wait_data d = {0};
240 	struct octep_ctrl_net_h2f_req *req = &d.data.req;
241 	struct octep_ctrl_net_h2f_resp *resp;
242 	int err;
243 
244 	init_send_req(&d.msg, req, link_info_sz, vfid);
245 	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_LINK_INFO;
246 	req->link_info.cmd = OCTEP_CTRL_NET_CMD_GET;
247 	err = octep_send_mbox_req(oct, &d, true);
248 	if (err < 0)
249 		return err;
250 
251 	resp = &d.data.resp;
252 	link_info->supported_modes = resp->link_info.supported_modes;
253 	link_info->advertised_modes = resp->link_info.advertised_modes;
254 	link_info->autoneg = resp->link_info.autoneg;
255 	link_info->pause = resp->link_info.pause;
256 	link_info->speed = resp->link_info.speed;
257 
258 	return 0;
259 }
260 
octep_ctrl_net_set_link_info(struct octep_device * oct,int vfid,struct octep_iface_link_info * link_info,bool wait_for_response)261 int octep_ctrl_net_set_link_info(struct octep_device *oct, int vfid,
262 				 struct octep_iface_link_info *link_info,
263 				 bool wait_for_response)
264 {
265 	struct octep_ctrl_net_wait_data d = {0};
266 	struct octep_ctrl_net_h2f_req *req = &d.data.req;
267 
268 	init_send_req(&d.msg, req, link_info_sz, vfid);
269 	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_LINK_INFO;
270 	req->link_info.cmd = OCTEP_CTRL_NET_CMD_SET;
271 	req->link_info.info.advertised_modes = link_info->advertised_modes;
272 	req->link_info.info.autoneg = link_info->autoneg;
273 	req->link_info.info.pause = link_info->pause;
274 	req->link_info.info.speed = link_info->speed;
275 
276 	return octep_send_mbox_req(oct, &d, wait_for_response);
277 }
278 
process_mbox_resp(struct octep_device * oct,struct octep_ctrl_mbox_msg * msg)279 static void process_mbox_resp(struct octep_device *oct,
280 			      struct octep_ctrl_mbox_msg *msg)
281 {
282 	struct octep_ctrl_net_wait_data *pos, *n;
283 
284 	list_for_each_entry_safe(pos, n, &oct->ctrl_req_wait_list, list) {
285 		if (pos->msg.hdr.s.msg_id == msg->hdr.s.msg_id) {
286 			memcpy(&pos->data.resp,
287 			       msg->sg_list[0].msg,
288 			       msg->hdr.s.sz);
289 			pos->done = 1;
290 			wake_up_interruptible_all(&oct->ctrl_req_wait_q);
291 			break;
292 		}
293 	}
294 }
295 
process_mbox_notify(struct octep_device * oct,struct octep_ctrl_mbox_msg * msg)296 static int process_mbox_notify(struct octep_device *oct,
297 			       struct octep_ctrl_mbox_msg *msg)
298 {
299 	struct net_device *netdev = oct->netdev;
300 	struct octep_ctrl_net_f2h_req *req;
301 	int cmd;
302 
303 	req = (struct octep_ctrl_net_f2h_req *)msg->sg_list[0].msg;
304 	cmd = req->hdr.s.cmd;
305 
306 	/* check if we support this command */
307 	if (octep_ctrl_net_f2h_cmd_versions[cmd] > OCTEP_CP_VERSION_CURRENT ||
308 	    octep_ctrl_net_f2h_cmd_versions[cmd] < OCTEP_CP_VERSION_CURRENT)
309 		return -EOPNOTSUPP;
310 
311 	switch (cmd) {
312 	case OCTEP_CTRL_NET_F2H_CMD_LINK_STATUS:
313 		if (netif_running(netdev)) {
314 			if (req->link.state) {
315 				dev_info(&oct->pdev->dev, "netif_carrier_on\n");
316 				netif_carrier_on(netdev);
317 			} else {
318 				dev_info(&oct->pdev->dev, "netif_carrier_off\n");
319 				netif_carrier_off(netdev);
320 			}
321 		}
322 		break;
323 	default:
324 		pr_info("Unknown mbox req : %u\n", req->hdr.s.cmd);
325 		break;
326 	}
327 
328 	return 0;
329 }
330 
octep_ctrl_net_recv_fw_messages(struct octep_device * oct)331 void octep_ctrl_net_recv_fw_messages(struct octep_device *oct)
332 {
333 	static u16 msg_sz = sizeof(union octep_ctrl_net_max_data);
334 	union octep_ctrl_net_max_data data = {0};
335 	struct octep_ctrl_mbox_msg msg = {0};
336 	int ret;
337 
338 	msg.hdr.s.sz = msg_sz;
339 	msg.sg_num = 1;
340 	msg.sg_list[0].sz = msg_sz;
341 	msg.sg_list[0].msg = &data;
342 	while (true) {
343 		/* mbox will overwrite msg.hdr.s.sz so initialize it */
344 		msg.hdr.s.sz = msg_sz;
345 		ret = octep_ctrl_mbox_recv(&oct->ctrl_mbox, (struct octep_ctrl_mbox_msg *)&msg);
346 		if (ret < 0)
347 			break;
348 
349 		if (msg.hdr.s.flags & OCTEP_CTRL_MBOX_MSG_HDR_FLAG_RESP)
350 			process_mbox_resp(oct, &msg);
351 		else if (msg.hdr.s.flags & OCTEP_CTRL_MBOX_MSG_HDR_FLAG_NOTIFY)
352 			process_mbox_notify(oct, &msg);
353 	}
354 }
355 
octep_ctrl_net_uninit(struct octep_device * oct)356 int octep_ctrl_net_uninit(struct octep_device *oct)
357 {
358 	struct octep_ctrl_net_wait_data *pos, *n;
359 
360 	list_for_each_entry_safe(pos, n, &oct->ctrl_req_wait_list, list)
361 		pos->done = 1;
362 
363 	wake_up_interruptible_all(&oct->ctrl_req_wait_q);
364 
365 	octep_ctrl_mbox_uninit(&oct->ctrl_mbox);
366 
367 	return 0;
368 }
369