1 // SPDX-License-Identifier: GPL-2.0 2 /* Marvell Octeon EP (EndPoint) Ethernet Driver 3 * 4 * Copyright (C) 2020 Marvell. 5 * 6 */ 7 8 #include <linux/types.h> 9 #include <linux/errno.h> 10 #include <linux/string.h> 11 #include <linux/mutex.h> 12 #include <linux/jiffies.h> 13 #include <linux/sched.h> 14 #include <linux/sched/signal.h> 15 #include <linux/io.h> 16 #include <linux/pci.h> 17 #include <linux/etherdevice.h> 18 #include <linux/vmalloc.h> 19 20 #include "octep_config.h" 21 #include "octep_main.h" 22 #include "octep_pfvf_mbox.h" 23 #include "octep_ctrl_net.h" 24 25 /* When a new command is implemented, the below table should be updated 26 * with new command and it's version info. 27 */ 28 static u32 pfvf_cmd_versions[OCTEP_PFVF_MBOX_CMD_MAX] = { 29 [0 ... OCTEP_PFVF_MBOX_CMD_DEV_REMOVE] = OCTEP_PFVF_MBOX_VERSION_V1, 30 [OCTEP_PFVF_MBOX_CMD_GET_FW_INFO ... OCTEP_PFVF_MBOX_NOTIF_LINK_STATUS] = 31 OCTEP_PFVF_MBOX_VERSION_V2 32 }; 33 34 static void octep_pfvf_validate_version(struct octep_device *oct, u32 vf_id, 35 union octep_pfvf_mbox_word cmd, 36 union octep_pfvf_mbox_word *rsp) 37 { 38 u32 vf_version = (u32)cmd.s_version.version; 39 40 dev_dbg(&oct->pdev->dev, "VF id:%d VF version:%d PF version:%d\n", 41 vf_id, vf_version, OCTEP_PFVF_MBOX_VERSION_CURRENT); 42 if (vf_version < OCTEP_PFVF_MBOX_VERSION_CURRENT) 43 rsp->s_version.version = vf_version; 44 else 45 rsp->s_version.version = OCTEP_PFVF_MBOX_VERSION_CURRENT; 46 47 oct->vf_info[vf_id].mbox_version = rsp->s_version.version; 48 dev_dbg(&oct->pdev->dev, "VF id:%d negotiated VF version:%d\n", 49 vf_id, oct->vf_info[vf_id].mbox_version); 50 51 rsp->s_version.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK; 52 } 53 54 static void octep_pfvf_get_link_status(struct octep_device *oct, u32 vf_id, 55 union octep_pfvf_mbox_word cmd, 56 union octep_pfvf_mbox_word *rsp) 57 { 58 int status; 59 60 status = octep_ctrl_net_get_link_status(oct, vf_id); 61 if (status < 0) { 62 rsp->s_link_status.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK; 63 dev_err(&oct->pdev->dev, "Get VF link status failed via host control Mbox\n"); 64 return; 65 } 66 rsp->s_link_status.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK; 67 rsp->s_link_status.status = status; 68 } 69 70 static void octep_pfvf_set_link_status(struct octep_device *oct, u32 vf_id, 71 union octep_pfvf_mbox_word cmd, 72 union octep_pfvf_mbox_word *rsp) 73 { 74 int err; 75 76 err = octep_ctrl_net_set_link_status(oct, vf_id, cmd.s_link_status.status, true); 77 if (err) { 78 rsp->s_link_status.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK; 79 dev_err(&oct->pdev->dev, "Set VF link status failed via host control Mbox\n"); 80 return; 81 } 82 rsp->s_link_status.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK; 83 } 84 85 static void octep_pfvf_set_rx_state(struct octep_device *oct, u32 vf_id, 86 union octep_pfvf_mbox_word cmd, 87 union octep_pfvf_mbox_word *rsp) 88 { 89 int err; 90 91 err = octep_ctrl_net_set_rx_state(oct, vf_id, cmd.s_link_state.state, true); 92 if (err) { 93 rsp->s_link_state.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK; 94 dev_err(&oct->pdev->dev, "Set VF Rx link state failed via host control Mbox\n"); 95 return; 96 } 97 rsp->s_link_state.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK; 98 } 99 100 static int octep_send_notification(struct octep_device *oct, u32 vf_id, 101 union octep_pfvf_mbox_word cmd) 102 { 103 u32 max_rings_per_vf, vf_mbox_queue; 104 struct octep_mbox *mbox; 105 106 /* check if VF PF Mailbox is compatible for this notification */ 107 if (pfvf_cmd_versions[cmd.s.opcode] > oct->vf_info[vf_id].mbox_version) { 108 dev_dbg(&oct->pdev->dev, "VF Mbox doesn't support Notification:%d on VF ver:%d\n", 109 cmd.s.opcode, oct->vf_info[vf_id].mbox_version); 110 return -EOPNOTSUPP; 111 } 112 113 max_rings_per_vf = CFG_GET_MAX_RPVF(oct->conf); 114 vf_mbox_queue = vf_id * max_rings_per_vf; 115 if (!oct->mbox[vf_mbox_queue]) { 116 dev_err(&oct->pdev->dev, "Notif obtained for bad mbox vf %d\n", vf_id); 117 return -EINVAL; 118 } 119 mbox = oct->mbox[vf_mbox_queue]; 120 121 mutex_lock(&mbox->lock); 122 writeq(cmd.u64, mbox->pf_vf_data_reg); 123 mutex_unlock(&mbox->lock); 124 125 return 0; 126 } 127 128 static void octep_pfvf_set_mtu(struct octep_device *oct, u32 vf_id, 129 union octep_pfvf_mbox_word cmd, 130 union octep_pfvf_mbox_word *rsp) 131 { 132 int err; 133 134 err = octep_ctrl_net_set_mtu(oct, vf_id, cmd.s_set_mtu.mtu, true); 135 if (err) { 136 rsp->s_set_mtu.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK; 137 dev_err(&oct->pdev->dev, "Set VF MTU failed via host control Mbox\n"); 138 return; 139 } 140 rsp->s_set_mtu.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK; 141 } 142 143 static void octep_pfvf_get_mtu(struct octep_device *oct, u32 vf_id, 144 union octep_pfvf_mbox_word cmd, 145 union octep_pfvf_mbox_word *rsp) 146 { 147 int max_rx_pktlen = oct->netdev->max_mtu + (ETH_HLEN + ETH_FCS_LEN); 148 149 rsp->s_set_mtu.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK; 150 rsp->s_get_mtu.mtu = max_rx_pktlen; 151 } 152 153 static void octep_pfvf_set_mac_addr(struct octep_device *oct, u32 vf_id, 154 union octep_pfvf_mbox_word cmd, 155 union octep_pfvf_mbox_word *rsp) 156 { 157 int err; 158 159 if (oct->vf_info[vf_id].flags & OCTEON_PFVF_FLAG_MAC_SET_BY_PF) { 160 dev_err(&oct->pdev->dev, 161 "VF%d attempted to override administrative set MAC address\n", 162 vf_id); 163 rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK; 164 return; 165 } 166 167 err = octep_ctrl_net_set_mac_addr(oct, vf_id, cmd.s_set_mac.mac_addr, true); 168 if (err) { 169 rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK; 170 dev_err(&oct->pdev->dev, "Set VF%d MAC address failed via host control Mbox\n", 171 vf_id); 172 return; 173 } 174 175 ether_addr_copy(oct->vf_info[vf_id].mac_addr, cmd.s_set_mac.mac_addr); 176 rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK; 177 } 178 179 static void octep_pfvf_get_mac_addr(struct octep_device *oct, u32 vf_id, 180 union octep_pfvf_mbox_word cmd, 181 union octep_pfvf_mbox_word *rsp) 182 { 183 int err; 184 185 if (oct->vf_info[vf_id].flags & OCTEON_PFVF_FLAG_MAC_SET_BY_PF) { 186 dev_dbg(&oct->pdev->dev, "VF%d MAC address set by PF\n", vf_id); 187 ether_addr_copy(rsp->s_set_mac.mac_addr, 188 oct->vf_info[vf_id].mac_addr); 189 rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK; 190 return; 191 } 192 err = octep_ctrl_net_get_mac_addr(oct, vf_id, rsp->s_set_mac.mac_addr); 193 if (err) { 194 rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK; 195 dev_err(&oct->pdev->dev, "Get VF%d MAC address failed via host control Mbox\n", 196 vf_id); 197 return; 198 } 199 ether_addr_copy(oct->vf_info[vf_id].mac_addr, rsp->s_set_mac.mac_addr); 200 rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK; 201 } 202 203 static void octep_pfvf_dev_remove(struct octep_device *oct, u32 vf_id, 204 union octep_pfvf_mbox_word cmd, 205 union octep_pfvf_mbox_word *rsp) 206 { 207 int err; 208 209 /* Reset VF-specific information maintained by the PF */ 210 memset(&oct->vf_info[vf_id], 0, sizeof(struct octep_pfvf_info)); 211 err = octep_ctrl_net_dev_remove(oct, vf_id); 212 if (err) { 213 rsp->s.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK; 214 dev_err(&oct->pdev->dev, "Failed to acknowledge fw of vf %d removal\n", 215 vf_id); 216 return; 217 } 218 rsp->s.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK; 219 } 220 221 static void octep_pfvf_get_fw_info(struct octep_device *oct, u32 vf_id, 222 union octep_pfvf_mbox_word cmd, 223 union octep_pfvf_mbox_word *rsp) 224 { 225 struct octep_fw_info fw_info; 226 int err; 227 228 err = octep_ctrl_net_get_info(oct, vf_id, &fw_info); 229 if (err) { 230 rsp->s_fw_info.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK; 231 dev_err(&oct->pdev->dev, "Get VF info failed via host control Mbox\n"); 232 return; 233 } 234 235 rsp->s_fw_info.pkind = fw_info.pkind; 236 rsp->s_fw_info.fsz = fw_info.fsz; 237 rsp->s_fw_info.rx_ol_flags = fw_info.rx_ol_flags; 238 rsp->s_fw_info.tx_ol_flags = fw_info.tx_ol_flags; 239 240 rsp->s_fw_info.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK; 241 } 242 243 static void octep_pfvf_set_offloads(struct octep_device *oct, u32 vf_id, 244 union octep_pfvf_mbox_word cmd, 245 union octep_pfvf_mbox_word *rsp) 246 { 247 struct octep_ctrl_net_offloads offloads = { 248 .rx_offloads = cmd.s_offloads.rx_ol_flags, 249 .tx_offloads = cmd.s_offloads.tx_ol_flags 250 }; 251 int err; 252 253 err = octep_ctrl_net_set_offloads(oct, vf_id, &offloads, true); 254 if (err) { 255 rsp->s_offloads.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK; 256 dev_err(&oct->pdev->dev, "Set VF offloads failed via host control Mbox\n"); 257 return; 258 } 259 rsp->s_offloads.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK; 260 } 261 262 int octep_setup_pfvf_mbox(struct octep_device *oct) 263 { 264 int i = 0, num_vfs = 0, rings_per_vf = 0; 265 int ring = 0; 266 267 num_vfs = oct->conf->sriov_cfg.active_vfs; 268 rings_per_vf = oct->conf->sriov_cfg.max_rings_per_vf; 269 270 for (i = 0; i < num_vfs; i++) { 271 ring = rings_per_vf * i; 272 oct->mbox[ring] = vzalloc(sizeof(*oct->mbox[ring])); 273 274 if (!oct->mbox[ring]) 275 goto free_mbox; 276 277 memset(oct->mbox[ring], 0, sizeof(struct octep_mbox)); 278 memset(&oct->vf_info[i], 0, sizeof(struct octep_pfvf_info)); 279 mutex_init(&oct->mbox[ring]->lock); 280 INIT_WORK(&oct->mbox[ring]->wk.work, octep_pfvf_mbox_work); 281 oct->mbox[ring]->wk.ctxptr = oct->mbox[ring]; 282 oct->mbox[ring]->oct = oct; 283 oct->mbox[ring]->vf_id = i; 284 oct->hw_ops.setup_mbox_regs(oct, ring); 285 } 286 return 0; 287 288 free_mbox: 289 while (i) { 290 i--; 291 ring = rings_per_vf * i; 292 cancel_work_sync(&oct->mbox[ring]->wk.work); 293 mutex_destroy(&oct->mbox[ring]->lock); 294 vfree(oct->mbox[ring]); 295 oct->mbox[ring] = NULL; 296 } 297 return -ENOMEM; 298 } 299 300 void octep_delete_pfvf_mbox(struct octep_device *oct) 301 { 302 int rings_per_vf = oct->conf->sriov_cfg.max_rings_per_vf; 303 int num_vfs = oct->conf->sriov_cfg.active_vfs; 304 int i = 0, ring = 0, vf_srn = 0; 305 306 for (i = 0; i < num_vfs; i++) { 307 ring = vf_srn + rings_per_vf * i; 308 if (!oct->mbox[ring]) 309 continue; 310 311 if (work_pending(&oct->mbox[ring]->wk.work)) 312 cancel_work_sync(&oct->mbox[ring]->wk.work); 313 314 mutex_destroy(&oct->mbox[ring]->lock); 315 vfree(oct->mbox[ring]); 316 oct->mbox[ring] = NULL; 317 } 318 } 319 320 static void octep_pfvf_pf_get_data(struct octep_device *oct, 321 struct octep_mbox *mbox, int vf_id, 322 union octep_pfvf_mbox_word cmd, 323 union octep_pfvf_mbox_word *rsp) 324 { 325 int length = 0; 326 int i = 0; 327 int err; 328 struct octep_iface_link_info link_info; 329 struct octep_iface_rx_stats rx_stats; 330 struct octep_iface_tx_stats tx_stats; 331 332 rsp->s_data.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK; 333 334 if (cmd.s_data.frag != OCTEP_PFVF_MBOX_MORE_FRAG_FLAG) { 335 mbox->config_data_index = 0; 336 memset(mbox->config_data, 0, MAX_VF_PF_MBOX_DATA_SIZE); 337 /* Based on the OPCODE CMD the PF driver 338 * specific API should be called to fetch 339 * the requested data 340 */ 341 switch (cmd.s.opcode) { 342 case OCTEP_PFVF_MBOX_CMD_GET_LINK_INFO: 343 memset(&link_info, 0, sizeof(link_info)); 344 err = octep_ctrl_net_get_link_info(oct, vf_id, &link_info); 345 if (!err) { 346 mbox->message_len = sizeof(link_info); 347 *((int32_t *)rsp->s_data.data) = mbox->message_len; 348 memcpy(mbox->config_data, (u8 *)&link_info, sizeof(link_info)); 349 } else { 350 rsp->s_data.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK; 351 return; 352 } 353 break; 354 case OCTEP_PFVF_MBOX_CMD_GET_STATS: 355 memset(&rx_stats, 0, sizeof(rx_stats)); 356 memset(&tx_stats, 0, sizeof(tx_stats)); 357 err = octep_ctrl_net_get_if_stats(oct, vf_id, &rx_stats, &tx_stats); 358 if (!err) { 359 mbox->message_len = sizeof(rx_stats) + sizeof(tx_stats); 360 *((int32_t *)rsp->s_data.data) = mbox->message_len; 361 memcpy(mbox->config_data, (u8 *)&rx_stats, sizeof(rx_stats)); 362 memcpy(mbox->config_data + sizeof(rx_stats), (u8 *)&tx_stats, 363 sizeof(tx_stats)); 364 365 } else { 366 rsp->s_data.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK; 367 return; 368 } 369 break; 370 } 371 *((int32_t *)rsp->s_data.data) = mbox->message_len; 372 return; 373 } 374 375 if (mbox->message_len > OCTEP_PFVF_MBOX_MAX_DATA_SIZE) 376 length = OCTEP_PFVF_MBOX_MAX_DATA_SIZE; 377 else 378 length = mbox->message_len; 379 380 mbox->message_len -= length; 381 382 for (i = 0; i < length; i++) { 383 rsp->s_data.data[i] = 384 mbox->config_data[mbox->config_data_index]; 385 mbox->config_data_index++; 386 } 387 } 388 389 void octep_pfvf_notify(struct octep_device *oct, struct octep_ctrl_mbox_msg *msg) 390 { 391 union octep_pfvf_mbox_word notif = { 0 }; 392 struct octep_ctrl_net_f2h_req *req; 393 394 req = (struct octep_ctrl_net_f2h_req *)msg->sg_list[0].msg; 395 switch (req->hdr.s.cmd) { 396 case OCTEP_CTRL_NET_F2H_CMD_LINK_STATUS: 397 notif.s_link_status.opcode = OCTEP_PFVF_MBOX_NOTIF_LINK_STATUS; 398 notif.s_link_status.status = req->link.state; 399 break; 400 default: 401 pr_info("Unknown mbox notif for vf: %u\n", 402 req->hdr.s.cmd); 403 return; 404 } 405 406 notif.s.type = OCTEP_PFVF_MBOX_TYPE_CMD; 407 octep_send_notification(oct, msg->hdr.s.vf_idx, notif); 408 } 409 410 void octep_pfvf_mbox_work(struct work_struct *work) 411 { 412 struct octep_pfvf_mbox_wk *wk = container_of(work, struct octep_pfvf_mbox_wk, work); 413 union octep_pfvf_mbox_word cmd = { 0 }; 414 union octep_pfvf_mbox_word rsp = { 0 }; 415 struct octep_mbox *mbox = NULL; 416 struct octep_device *oct = NULL; 417 int vf_id; 418 419 mbox = (struct octep_mbox *)wk->ctxptr; 420 oct = (struct octep_device *)mbox->oct; 421 vf_id = mbox->vf_id; 422 423 mutex_lock(&mbox->lock); 424 cmd.u64 = readq(mbox->vf_pf_data_reg); 425 rsp.u64 = 0; 426 427 switch (cmd.s.opcode) { 428 case OCTEP_PFVF_MBOX_CMD_VERSION: 429 octep_pfvf_validate_version(oct, vf_id, cmd, &rsp); 430 break; 431 case OCTEP_PFVF_MBOX_CMD_GET_LINK_STATUS: 432 octep_pfvf_get_link_status(oct, vf_id, cmd, &rsp); 433 break; 434 case OCTEP_PFVF_MBOX_CMD_SET_LINK_STATUS: 435 octep_pfvf_set_link_status(oct, vf_id, cmd, &rsp); 436 break; 437 case OCTEP_PFVF_MBOX_CMD_SET_RX_STATE: 438 octep_pfvf_set_rx_state(oct, vf_id, cmd, &rsp); 439 break; 440 case OCTEP_PFVF_MBOX_CMD_SET_MTU: 441 octep_pfvf_set_mtu(oct, vf_id, cmd, &rsp); 442 break; 443 case OCTEP_PFVF_MBOX_CMD_SET_MAC_ADDR: 444 octep_pfvf_set_mac_addr(oct, vf_id, cmd, &rsp); 445 break; 446 case OCTEP_PFVF_MBOX_CMD_GET_MAC_ADDR: 447 octep_pfvf_get_mac_addr(oct, vf_id, cmd, &rsp); 448 break; 449 case OCTEP_PFVF_MBOX_CMD_GET_LINK_INFO: 450 case OCTEP_PFVF_MBOX_CMD_GET_STATS: 451 octep_pfvf_pf_get_data(oct, mbox, vf_id, cmd, &rsp); 452 break; 453 case OCTEP_PFVF_MBOX_CMD_GET_MTU: 454 octep_pfvf_get_mtu(oct, vf_id, cmd, &rsp); 455 break; 456 case OCTEP_PFVF_MBOX_CMD_DEV_REMOVE: 457 octep_pfvf_dev_remove(oct, vf_id, cmd, &rsp); 458 break; 459 case OCTEP_PFVF_MBOX_CMD_GET_FW_INFO: 460 octep_pfvf_get_fw_info(oct, vf_id, cmd, &rsp); 461 break; 462 case OCTEP_PFVF_MBOX_CMD_SET_OFFLOADS: 463 octep_pfvf_set_offloads(oct, vf_id, cmd, &rsp); 464 break; 465 default: 466 dev_err(&oct->pdev->dev, "PF-VF mailbox: invalid opcode %d\n", cmd.s.opcode); 467 rsp.s.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK; 468 break; 469 } 470 writeq(rsp.u64, mbox->vf_pf_data_reg); 471 mutex_unlock(&mbox->lock); 472 } 473