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