Loading...
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
21static const u32 req_hdr_sz = sizeof(union octep_ctrl_net_req_hdr);
22static const u32 mtu_sz = sizeof(struct octep_ctrl_net_h2f_req_cmd_mtu);
23static const u32 mac_sz = sizeof(struct octep_ctrl_net_h2f_req_cmd_mac);
24static const u32 state_sz = sizeof(struct octep_ctrl_net_h2f_req_cmd_state);
25static const u32 link_info_sz = sizeof(struct octep_ctrl_net_link_info);
26static const u32 offloads_sz = sizeof(struct octep_ctrl_net_offloads);
27static atomic_t ctrl_net_msg_id;
28
29/* Control plane version in which OCTEP_CTRL_NET_H2F_CMD was added */
30static 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 */
38static 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
43static 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
59static 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
101int 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
127int 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
143int 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
158int 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
173int 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
191int 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
205int 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
223int 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
237int 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
258int 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
283int 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
301static 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
318static 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
358void 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
383int 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
405int 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
418int 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
434int 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}
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
12#include "octep_config.h"
13#include "octep_main.h"
14#include "octep_ctrl_net.h"
15
16int octep_get_link_status(struct octep_device *oct)
17{
18 struct octep_ctrl_net_h2f_req req = {};
19 struct octep_ctrl_net_h2f_resp *resp;
20 struct octep_ctrl_mbox_msg msg = {};
21 int err;
22
23 req.hdr.cmd = OCTEP_CTRL_NET_H2F_CMD_LINK_STATUS;
24 req.link.cmd = OCTEP_CTRL_NET_CMD_GET;
25
26 msg.hdr.flags = OCTEP_CTRL_MBOX_MSG_HDR_FLAG_REQ;
27 msg.hdr.sizew = OCTEP_CTRL_NET_H2F_STATE_REQ_SZW;
28 msg.msg = &req;
29 err = octep_ctrl_mbox_send(&oct->ctrl_mbox, &msg);
30 if (err)
31 return err;
32
33 resp = (struct octep_ctrl_net_h2f_resp *)&req;
34 return resp->link.state;
35}
36
37void octep_set_link_status(struct octep_device *oct, bool up)
38{
39 struct octep_ctrl_net_h2f_req req = {};
40 struct octep_ctrl_mbox_msg msg = {};
41
42 req.hdr.cmd = OCTEP_CTRL_NET_H2F_CMD_LINK_STATUS;
43 req.link.cmd = OCTEP_CTRL_NET_CMD_SET;
44 req.link.state = (up) ? OCTEP_CTRL_NET_STATE_UP : OCTEP_CTRL_NET_STATE_DOWN;
45
46 msg.hdr.flags = OCTEP_CTRL_MBOX_MSG_HDR_FLAG_REQ;
47 msg.hdr.sizew = OCTEP_CTRL_NET_H2F_STATE_REQ_SZW;
48 msg.msg = &req;
49 octep_ctrl_mbox_send(&oct->ctrl_mbox, &msg);
50}
51
52void octep_set_rx_state(struct octep_device *oct, bool up)
53{
54 struct octep_ctrl_net_h2f_req req = {};
55 struct octep_ctrl_mbox_msg msg = {};
56
57 req.hdr.cmd = OCTEP_CTRL_NET_H2F_CMD_RX_STATE;
58 req.link.cmd = OCTEP_CTRL_NET_CMD_SET;
59 req.link.state = (up) ? OCTEP_CTRL_NET_STATE_UP : OCTEP_CTRL_NET_STATE_DOWN;
60
61 msg.hdr.flags = OCTEP_CTRL_MBOX_MSG_HDR_FLAG_REQ;
62 msg.hdr.sizew = OCTEP_CTRL_NET_H2F_STATE_REQ_SZW;
63 msg.msg = &req;
64 octep_ctrl_mbox_send(&oct->ctrl_mbox, &msg);
65}
66
67int octep_get_mac_addr(struct octep_device *oct, u8 *addr)
68{
69 struct octep_ctrl_net_h2f_req req = {};
70 struct octep_ctrl_net_h2f_resp *resp;
71 struct octep_ctrl_mbox_msg msg = {};
72 int err;
73
74 req.hdr.cmd = OCTEP_CTRL_NET_H2F_CMD_MAC;
75 req.link.cmd = OCTEP_CTRL_NET_CMD_GET;
76
77 msg.hdr.flags = OCTEP_CTRL_MBOX_MSG_HDR_FLAG_REQ;
78 msg.hdr.sizew = OCTEP_CTRL_NET_H2F_MAC_REQ_SZW;
79 msg.msg = &req;
80 err = octep_ctrl_mbox_send(&oct->ctrl_mbox, &msg);
81 if (err)
82 return err;
83
84 resp = (struct octep_ctrl_net_h2f_resp *)&req;
85 memcpy(addr, resp->mac.addr, ETH_ALEN);
86
87 return err;
88}
89
90int octep_set_mac_addr(struct octep_device *oct, u8 *addr)
91{
92 struct octep_ctrl_net_h2f_req req = {};
93 struct octep_ctrl_mbox_msg msg = {};
94
95 req.hdr.cmd = OCTEP_CTRL_NET_H2F_CMD_MAC;
96 req.mac.cmd = OCTEP_CTRL_NET_CMD_SET;
97 memcpy(&req.mac.addr, addr, ETH_ALEN);
98
99 msg.hdr.flags = OCTEP_CTRL_MBOX_MSG_HDR_FLAG_REQ;
100 msg.hdr.sizew = OCTEP_CTRL_NET_H2F_MAC_REQ_SZW;
101 msg.msg = &req;
102
103 return octep_ctrl_mbox_send(&oct->ctrl_mbox, &msg);
104}
105
106int octep_set_mtu(struct octep_device *oct, int mtu)
107{
108 struct octep_ctrl_net_h2f_req req = {};
109 struct octep_ctrl_mbox_msg msg = {};
110
111 req.hdr.cmd = OCTEP_CTRL_NET_H2F_CMD_MTU;
112 req.mtu.cmd = OCTEP_CTRL_NET_CMD_SET;
113 req.mtu.val = mtu;
114
115 msg.hdr.flags = OCTEP_CTRL_MBOX_MSG_HDR_FLAG_REQ;
116 msg.hdr.sizew = OCTEP_CTRL_NET_H2F_MTU_REQ_SZW;
117 msg.msg = &req;
118
119 return octep_ctrl_mbox_send(&oct->ctrl_mbox, &msg);
120}
121
122int octep_get_if_stats(struct octep_device *oct)
123{
124 void __iomem *iface_rx_stats;
125 void __iomem *iface_tx_stats;
126 struct octep_ctrl_net_h2f_req req = {};
127 struct octep_ctrl_mbox_msg msg = {};
128 int err;
129
130 req.hdr.cmd = OCTEP_CTRL_NET_H2F_CMD_GET_IF_STATS;
131 req.mac.cmd = OCTEP_CTRL_NET_CMD_GET;
132 req.get_stats.offset = oct->ctrl_mbox_ifstats_offset;
133
134 msg.hdr.flags = OCTEP_CTRL_MBOX_MSG_HDR_FLAG_REQ;
135 msg.hdr.sizew = OCTEP_CTRL_NET_H2F_GET_STATS_REQ_SZW;
136 msg.msg = &req;
137 err = octep_ctrl_mbox_send(&oct->ctrl_mbox, &msg);
138 if (err)
139 return err;
140
141 iface_rx_stats = oct->ctrl_mbox.barmem + oct->ctrl_mbox_ifstats_offset;
142 iface_tx_stats = oct->ctrl_mbox.barmem + oct->ctrl_mbox_ifstats_offset +
143 sizeof(struct octep_iface_rx_stats);
144 memcpy_fromio(&oct->iface_rx_stats, iface_rx_stats, sizeof(struct octep_iface_rx_stats));
145 memcpy_fromio(&oct->iface_tx_stats, iface_tx_stats, sizeof(struct octep_iface_tx_stats));
146
147 return err;
148}
149
150int octep_get_link_info(struct octep_device *oct)
151{
152 struct octep_ctrl_net_h2f_req req = {};
153 struct octep_ctrl_net_h2f_resp *resp;
154 struct octep_ctrl_mbox_msg msg = {};
155 int err;
156
157 req.hdr.cmd = OCTEP_CTRL_NET_H2F_CMD_LINK_INFO;
158 req.mac.cmd = OCTEP_CTRL_NET_CMD_GET;
159
160 msg.hdr.flags = OCTEP_CTRL_MBOX_MSG_HDR_FLAG_REQ;
161 msg.hdr.sizew = OCTEP_CTRL_NET_H2F_LINK_INFO_REQ_SZW;
162 msg.msg = &req;
163 err = octep_ctrl_mbox_send(&oct->ctrl_mbox, &msg);
164 if (err)
165 return err;
166
167 resp = (struct octep_ctrl_net_h2f_resp *)&req;
168 oct->link_info.supported_modes = resp->link_info.supported_modes;
169 oct->link_info.advertised_modes = resp->link_info.advertised_modes;
170 oct->link_info.autoneg = resp->link_info.autoneg;
171 oct->link_info.pause = resp->link_info.pause;
172 oct->link_info.speed = resp->link_info.speed;
173
174 return err;
175}
176
177int octep_set_link_info(struct octep_device *oct, struct octep_iface_link_info *link_info)
178{
179 struct octep_ctrl_net_h2f_req req = {};
180 struct octep_ctrl_mbox_msg msg = {};
181
182 req.hdr.cmd = OCTEP_CTRL_NET_H2F_CMD_LINK_INFO;
183 req.link_info.cmd = OCTEP_CTRL_NET_CMD_SET;
184 req.link_info.info.advertised_modes = link_info->advertised_modes;
185 req.link_info.info.autoneg = link_info->autoneg;
186 req.link_info.info.pause = link_info->pause;
187 req.link_info.info.speed = link_info->speed;
188
189 msg.hdr.flags = OCTEP_CTRL_MBOX_MSG_HDR_FLAG_REQ;
190 msg.hdr.sizew = OCTEP_CTRL_NET_H2F_LINK_INFO_REQ_SZW;
191 msg.msg = &req;
192
193 return octep_ctrl_mbox_send(&oct->ctrl_mbox, &msg);
194}