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 err = octep_ctrl_net_set_mac_addr(oct, vf_id, cmd.s_set_mac.mac_addr, true); 160 if (err) { 161 rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK; 162 dev_err(&oct->pdev->dev, "Set VF MAC address failed via host control Mbox\n"); 163 return; 164 } 165 rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK; 166 } 167 168 static void octep_pfvf_get_mac_addr(struct octep_device *oct, u32 vf_id, 169 union octep_pfvf_mbox_word cmd, 170 union octep_pfvf_mbox_word *rsp) 171 { 172 int err; 173 174 err = octep_ctrl_net_get_mac_addr(oct, vf_id, rsp->s_set_mac.mac_addr); 175 if (err) { 176 rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK; 177 dev_err(&oct->pdev->dev, "Get VF MAC address failed via host control Mbox\n"); 178 return; 179 } 180 rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK; 181 } 182 183 static void octep_pfvf_dev_remove(struct octep_device *oct, u32 vf_id, 184 union octep_pfvf_mbox_word cmd, 185 union octep_pfvf_mbox_word *rsp) 186 { 187 int err; 188 189 err = octep_ctrl_net_dev_remove(oct, vf_id); 190 if (err) { 191 rsp->s.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK; 192 dev_err(&oct->pdev->dev, "Failed to acknowledge fw of vf %d removal\n", 193 vf_id); 194 return; 195 } 196 rsp->s.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK; 197 } 198 199 static void octep_pfvf_get_fw_info(struct octep_device *oct, u32 vf_id, 200 union octep_pfvf_mbox_word cmd, 201 union octep_pfvf_mbox_word *rsp) 202 { 203 struct octep_fw_info fw_info; 204 int err; 205 206 err = octep_ctrl_net_get_info(oct, vf_id, &fw_info); 207 if (err) { 208 rsp->s_fw_info.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK; 209 dev_err(&oct->pdev->dev, "Get VF info failed via host control Mbox\n"); 210 return; 211 } 212 213 rsp->s_fw_info.pkind = fw_info.pkind; 214 rsp->s_fw_info.fsz = fw_info.fsz; 215 rsp->s_fw_info.rx_ol_flags = fw_info.rx_ol_flags; 216 rsp->s_fw_info.tx_ol_flags = fw_info.tx_ol_flags; 217 218 rsp->s_fw_info.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK; 219 } 220 221 static void octep_pfvf_set_offloads(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_ctrl_net_offloads offloads = { 226 .rx_offloads = cmd.s_offloads.rx_ol_flags, 227 .tx_offloads = cmd.s_offloads.tx_ol_flags 228 }; 229 int err; 230 231 err = octep_ctrl_net_set_offloads(oct, vf_id, &offloads, true); 232 if (err) { 233 rsp->s_offloads.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK; 234 dev_err(&oct->pdev->dev, "Set VF offloads failed via host control Mbox\n"); 235 return; 236 } 237 rsp->s_offloads.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK; 238 } 239 240 int octep_setup_pfvf_mbox(struct octep_device *oct) 241 { 242 int i = 0, num_vfs = 0, rings_per_vf = 0; 243 int ring = 0; 244 245 num_vfs = oct->conf->sriov_cfg.active_vfs; 246 rings_per_vf = oct->conf->sriov_cfg.max_rings_per_vf; 247 248 for (i = 0; i < num_vfs; i++) { 249 ring = rings_per_vf * i; 250 oct->mbox[ring] = vzalloc(sizeof(*oct->mbox[ring])); 251 252 if (!oct->mbox[ring]) 253 goto free_mbox; 254 255 memset(oct->mbox[ring], 0, sizeof(struct octep_mbox)); 256 memset(&oct->vf_info[i], 0, sizeof(struct octep_pfvf_info)); 257 mutex_init(&oct->mbox[ring]->lock); 258 INIT_WORK(&oct->mbox[ring]->wk.work, octep_pfvf_mbox_work); 259 oct->mbox[ring]->wk.ctxptr = oct->mbox[ring]; 260 oct->mbox[ring]->oct = oct; 261 oct->mbox[ring]->vf_id = i; 262 oct->hw_ops.setup_mbox_regs(oct, ring); 263 } 264 return 0; 265 266 free_mbox: 267 while (i) { 268 i--; 269 ring = rings_per_vf * i; 270 cancel_work_sync(&oct->mbox[ring]->wk.work); 271 mutex_destroy(&oct->mbox[ring]->lock); 272 vfree(oct->mbox[ring]); 273 oct->mbox[ring] = NULL; 274 } 275 return -ENOMEM; 276 } 277 278 void octep_delete_pfvf_mbox(struct octep_device *oct) 279 { 280 int rings_per_vf = oct->conf->sriov_cfg.max_rings_per_vf; 281 int num_vfs = oct->conf->sriov_cfg.active_vfs; 282 int i = 0, ring = 0, vf_srn = 0; 283 284 for (i = 0; i < num_vfs; i++) { 285 ring = vf_srn + rings_per_vf * i; 286 if (!oct->mbox[ring]) 287 continue; 288 289 if (work_pending(&oct->mbox[ring]->wk.work)) 290 cancel_work_sync(&oct->mbox[ring]->wk.work); 291 292 mutex_destroy(&oct->mbox[ring]->lock); 293 vfree(oct->mbox[ring]); 294 oct->mbox[ring] = NULL; 295 } 296 } 297 298 static void octep_pfvf_pf_get_data(struct octep_device *oct, 299 struct octep_mbox *mbox, int vf_id, 300 union octep_pfvf_mbox_word cmd, 301 union octep_pfvf_mbox_word *rsp) 302 { 303 int length = 0; 304 int i = 0; 305 int err; 306 struct octep_iface_link_info link_info; 307 struct octep_iface_rx_stats rx_stats; 308 struct octep_iface_tx_stats tx_stats; 309 310 rsp->s_data.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK; 311 312 if (cmd.s_data.frag != OCTEP_PFVF_MBOX_MORE_FRAG_FLAG) { 313 mbox->config_data_index = 0; 314 memset(mbox->config_data, 0, MAX_VF_PF_MBOX_DATA_SIZE); 315 /* Based on the OPCODE CMD the PF driver 316 * specific API should be called to fetch 317 * the requested data 318 */ 319 switch (cmd.s.opcode) { 320 case OCTEP_PFVF_MBOX_CMD_GET_LINK_INFO: 321 memset(&link_info, 0, sizeof(link_info)); 322 err = octep_ctrl_net_get_link_info(oct, vf_id, &link_info); 323 if (!err) { 324 mbox->message_len = sizeof(link_info); 325 *((int32_t *)rsp->s_data.data) = mbox->message_len; 326 memcpy(mbox->config_data, (u8 *)&link_info, sizeof(link_info)); 327 } else { 328 rsp->s_data.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK; 329 return; 330 } 331 break; 332 case OCTEP_PFVF_MBOX_CMD_GET_STATS: 333 memset(&rx_stats, 0, sizeof(rx_stats)); 334 memset(&tx_stats, 0, sizeof(tx_stats)); 335 err = octep_ctrl_net_get_if_stats(oct, vf_id, &rx_stats, &tx_stats); 336 if (!err) { 337 mbox->message_len = sizeof(rx_stats) + sizeof(tx_stats); 338 *((int32_t *)rsp->s_data.data) = mbox->message_len; 339 memcpy(mbox->config_data, (u8 *)&rx_stats, sizeof(rx_stats)); 340 memcpy(mbox->config_data + sizeof(rx_stats), (u8 *)&tx_stats, 341 sizeof(tx_stats)); 342 343 } else { 344 rsp->s_data.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK; 345 return; 346 } 347 break; 348 } 349 *((int32_t *)rsp->s_data.data) = mbox->message_len; 350 return; 351 } 352 353 if (mbox->message_len > OCTEP_PFVF_MBOX_MAX_DATA_SIZE) 354 length = OCTEP_PFVF_MBOX_MAX_DATA_SIZE; 355 else 356 length = mbox->message_len; 357 358 mbox->message_len -= length; 359 360 for (i = 0; i < length; i++) { 361 rsp->s_data.data[i] = 362 mbox->config_data[mbox->config_data_index]; 363 mbox->config_data_index++; 364 } 365 } 366 367 void octep_pfvf_notify(struct octep_device *oct, struct octep_ctrl_mbox_msg *msg) 368 { 369 union octep_pfvf_mbox_word notif = { 0 }; 370 struct octep_ctrl_net_f2h_req *req; 371 372 req = (struct octep_ctrl_net_f2h_req *)msg->sg_list[0].msg; 373 switch (req->hdr.s.cmd) { 374 case OCTEP_CTRL_NET_F2H_CMD_LINK_STATUS: 375 notif.s_link_status.opcode = OCTEP_PFVF_MBOX_NOTIF_LINK_STATUS; 376 notif.s_link_status.status = req->link.state; 377 break; 378 default: 379 pr_info("Unknown mbox notif for vf: %u\n", 380 req->hdr.s.cmd); 381 return; 382 } 383 384 notif.s.type = OCTEP_PFVF_MBOX_TYPE_CMD; 385 octep_send_notification(oct, msg->hdr.s.vf_idx, notif); 386 } 387 388 void octep_pfvf_mbox_work(struct work_struct *work) 389 { 390 struct octep_pfvf_mbox_wk *wk = container_of(work, struct octep_pfvf_mbox_wk, work); 391 union octep_pfvf_mbox_word cmd = { 0 }; 392 union octep_pfvf_mbox_word rsp = { 0 }; 393 struct octep_mbox *mbox = NULL; 394 struct octep_device *oct = NULL; 395 int vf_id; 396 397 mbox = (struct octep_mbox *)wk->ctxptr; 398 oct = (struct octep_device *)mbox->oct; 399 vf_id = mbox->vf_id; 400 401 mutex_lock(&mbox->lock); 402 cmd.u64 = readq(mbox->vf_pf_data_reg); 403 rsp.u64 = 0; 404 405 switch (cmd.s.opcode) { 406 case OCTEP_PFVF_MBOX_CMD_VERSION: 407 octep_pfvf_validate_version(oct, vf_id, cmd, &rsp); 408 break; 409 case OCTEP_PFVF_MBOX_CMD_GET_LINK_STATUS: 410 octep_pfvf_get_link_status(oct, vf_id, cmd, &rsp); 411 break; 412 case OCTEP_PFVF_MBOX_CMD_SET_LINK_STATUS: 413 octep_pfvf_set_link_status(oct, vf_id, cmd, &rsp); 414 break; 415 case OCTEP_PFVF_MBOX_CMD_SET_RX_STATE: 416 octep_pfvf_set_rx_state(oct, vf_id, cmd, &rsp); 417 break; 418 case OCTEP_PFVF_MBOX_CMD_SET_MTU: 419 octep_pfvf_set_mtu(oct, vf_id, cmd, &rsp); 420 break; 421 case OCTEP_PFVF_MBOX_CMD_SET_MAC_ADDR: 422 octep_pfvf_set_mac_addr(oct, vf_id, cmd, &rsp); 423 break; 424 case OCTEP_PFVF_MBOX_CMD_GET_MAC_ADDR: 425 octep_pfvf_get_mac_addr(oct, vf_id, cmd, &rsp); 426 break; 427 case OCTEP_PFVF_MBOX_CMD_GET_LINK_INFO: 428 case OCTEP_PFVF_MBOX_CMD_GET_STATS: 429 octep_pfvf_pf_get_data(oct, mbox, vf_id, cmd, &rsp); 430 break; 431 case OCTEP_PFVF_MBOX_CMD_GET_MTU: 432 octep_pfvf_get_mtu(oct, vf_id, cmd, &rsp); 433 break; 434 case OCTEP_PFVF_MBOX_CMD_DEV_REMOVE: 435 octep_pfvf_dev_remove(oct, vf_id, cmd, &rsp); 436 break; 437 case OCTEP_PFVF_MBOX_CMD_GET_FW_INFO: 438 octep_pfvf_get_fw_info(oct, vf_id, cmd, &rsp); 439 break; 440 case OCTEP_PFVF_MBOX_CMD_SET_OFFLOADS: 441 octep_pfvf_set_offloads(oct, vf_id, cmd, &rsp); 442 break; 443 default: 444 dev_err(&oct->pdev->dev, "PF-VF mailbox: invalid opcode %d\n", cmd.s.opcode); 445 rsp.s.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK; 446 break; 447 } 448 writeq(rsp.u64, mbox->vf_pf_data_reg); 449 mutex_unlock(&mbox->lock); 450 } 451