xref: /openbmc/linux/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
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