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