603 lines · c
1/* Broadcom NetXtreme-C/E network driver.2 *3 * Copyright (c) 2016-2017 Broadcom Limited4 *5 * This program is free software; you can redistribute it and/or modify6 * it under the terms of the GNU General Public License as published by7 * the Free Software Foundation.8 */9#include <linux/pci.h>10#include <linux/netdevice.h>11#include <linux/etherdevice.h>12#include <linux/rtnetlink.h>13#include <linux/jhash.h>14#include <net/pkt_cls.h>15 16#include "bnxt_hsi.h"17#include "bnxt.h"18#include "bnxt_hwrm.h"19#include "bnxt_vfr.h"20#include "bnxt_devlink.h"21#include "bnxt_tc.h"22 23#ifdef CONFIG_BNXT_SRIOV24 25#define CFA_HANDLE_INVALID 0xffff26#define VF_IDX_INVALID 0xffff27 28static int hwrm_cfa_vfr_alloc(struct bnxt *bp, u16 vf_idx,29 u16 *tx_cfa_action, u16 *rx_cfa_code)30{31 struct hwrm_cfa_vfr_alloc_output *resp;32 struct hwrm_cfa_vfr_alloc_input *req;33 int rc;34 35 rc = hwrm_req_init(bp, req, HWRM_CFA_VFR_ALLOC);36 if (!rc) {37 req->vf_id = cpu_to_le16(vf_idx);38 sprintf(req->vfr_name, "vfr%d", vf_idx);39 40 resp = hwrm_req_hold(bp, req);41 rc = hwrm_req_send(bp, req);42 if (!rc) {43 *tx_cfa_action = le16_to_cpu(resp->tx_cfa_action);44 *rx_cfa_code = le16_to_cpu(resp->rx_cfa_code);45 netdev_dbg(bp->dev, "tx_cfa_action=0x%x, rx_cfa_code=0x%x",46 *tx_cfa_action, *rx_cfa_code);47 }48 hwrm_req_drop(bp, req);49 }50 if (rc)51 netdev_info(bp->dev, "%s error rc=%d\n", __func__, rc);52 return rc;53}54 55static int hwrm_cfa_vfr_free(struct bnxt *bp, u16 vf_idx)56{57 struct hwrm_cfa_vfr_free_input *req;58 int rc;59 60 rc = hwrm_req_init(bp, req, HWRM_CFA_VFR_FREE);61 if (!rc) {62 sprintf(req->vfr_name, "vfr%d", vf_idx);63 rc = hwrm_req_send(bp, req);64 }65 if (rc)66 netdev_info(bp->dev, "%s error rc=%d\n", __func__, rc);67 return rc;68}69 70static int bnxt_hwrm_vfr_qcfg(struct bnxt *bp, struct bnxt_vf_rep *vf_rep,71 u16 *max_mtu)72{73 struct hwrm_func_qcfg_output *resp;74 struct hwrm_func_qcfg_input *req;75 u16 mtu;76 int rc;77 78 rc = hwrm_req_init(bp, req, HWRM_FUNC_QCFG);79 if (rc)80 return rc;81 82 req->fid = cpu_to_le16(bp->pf.vf[vf_rep->vf_idx].fw_fid);83 resp = hwrm_req_hold(bp, req);84 rc = hwrm_req_send(bp, req);85 if (!rc) {86 mtu = le16_to_cpu(resp->max_mtu_configured);87 if (!mtu)88 *max_mtu = BNXT_MAX_MTU;89 else90 *max_mtu = mtu;91 }92 hwrm_req_drop(bp, req);93 return rc;94}95 96static int bnxt_vf_rep_open(struct net_device *dev)97{98 struct bnxt_vf_rep *vf_rep = netdev_priv(dev);99 struct bnxt *bp = vf_rep->bp;100 101 /* Enable link and TX only if the parent PF is open. */102 if (netif_running(bp->dev)) {103 netif_carrier_on(dev);104 netif_tx_start_all_queues(dev);105 }106 return 0;107}108 109static int bnxt_vf_rep_close(struct net_device *dev)110{111 netif_carrier_off(dev);112 netif_tx_disable(dev);113 114 return 0;115}116 117static netdev_tx_t bnxt_vf_rep_xmit(struct sk_buff *skb,118 struct net_device *dev)119{120 struct bnxt_vf_rep *vf_rep = netdev_priv(dev);121 int rc, len = skb->len;122 123 skb_dst_drop(skb);124 dst_hold((struct dst_entry *)vf_rep->dst);125 skb_dst_set(skb, (struct dst_entry *)vf_rep->dst);126 skb->dev = vf_rep->dst->u.port_info.lower_dev;127 128 rc = dev_queue_xmit(skb);129 if (!rc) {130 vf_rep->tx_stats.packets++;131 vf_rep->tx_stats.bytes += len;132 }133 return rc;134}135 136static void137bnxt_vf_rep_get_stats64(struct net_device *dev,138 struct rtnl_link_stats64 *stats)139{140 struct bnxt_vf_rep *vf_rep = netdev_priv(dev);141 142 stats->rx_packets = vf_rep->rx_stats.packets;143 stats->rx_bytes = vf_rep->rx_stats.bytes;144 stats->tx_packets = vf_rep->tx_stats.packets;145 stats->tx_bytes = vf_rep->tx_stats.bytes;146}147 148static int bnxt_vf_rep_setup_tc_block_cb(enum tc_setup_type type,149 void *type_data,150 void *cb_priv)151{152 struct bnxt_vf_rep *vf_rep = cb_priv;153 struct bnxt *bp = vf_rep->bp;154 int vf_fid = bp->pf.vf[vf_rep->vf_idx].fw_fid;155 156 if (!bnxt_tc_flower_enabled(vf_rep->bp) ||157 !tc_cls_can_offload_and_chain0(bp->dev, type_data))158 return -EOPNOTSUPP;159 160 switch (type) {161 case TC_SETUP_CLSFLOWER:162 return bnxt_tc_setup_flower(bp, vf_fid, type_data);163 default:164 return -EOPNOTSUPP;165 }166}167 168static LIST_HEAD(bnxt_vf_block_cb_list);169 170static int bnxt_vf_rep_setup_tc(struct net_device *dev, enum tc_setup_type type,171 void *type_data)172{173 struct bnxt_vf_rep *vf_rep = netdev_priv(dev);174 175 switch (type) {176 case TC_SETUP_BLOCK:177 return flow_block_cb_setup_simple(type_data,178 &bnxt_vf_block_cb_list,179 bnxt_vf_rep_setup_tc_block_cb,180 vf_rep, vf_rep, true);181 default:182 return -EOPNOTSUPP;183 }184}185 186struct net_device *bnxt_get_vf_rep(struct bnxt *bp, u16 cfa_code)187{188 u16 vf_idx;189 190 if (cfa_code && bp->cfa_code_map && BNXT_PF(bp)) {191 vf_idx = bp->cfa_code_map[cfa_code];192 if (vf_idx != VF_IDX_INVALID)193 return bp->vf_reps[vf_idx]->dev;194 }195 return NULL;196}197 198void bnxt_vf_rep_rx(struct bnxt *bp, struct sk_buff *skb)199{200 struct bnxt_vf_rep *vf_rep = netdev_priv(skb->dev);201 202 vf_rep->rx_stats.bytes += skb->len;203 vf_rep->rx_stats.packets++;204 205 netif_receive_skb(skb);206}207 208static int bnxt_vf_rep_get_phys_port_name(struct net_device *dev, char *buf,209 size_t len)210{211 struct bnxt_vf_rep *vf_rep = netdev_priv(dev);212 struct pci_dev *pf_pdev = vf_rep->bp->pdev;213 int rc;214 215 rc = snprintf(buf, len, "pf%dvf%d", PCI_FUNC(pf_pdev->devfn),216 vf_rep->vf_idx);217 if (rc >= len)218 return -EOPNOTSUPP;219 return 0;220}221 222static void bnxt_vf_rep_get_drvinfo(struct net_device *dev,223 struct ethtool_drvinfo *info)224{225 strscpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));226}227 228static int bnxt_vf_rep_get_port_parent_id(struct net_device *dev,229 struct netdev_phys_item_id *ppid)230{231 struct bnxt_vf_rep *vf_rep = netdev_priv(dev);232 233 /* as only PORT_PARENT_ID is supported currently use common code234 * between PF and VF-rep for now.235 */236 return bnxt_get_port_parent_id(vf_rep->bp->dev, ppid);237}238 239static const struct ethtool_ops bnxt_vf_rep_ethtool_ops = {240 .get_drvinfo = bnxt_vf_rep_get_drvinfo241};242 243static const struct net_device_ops bnxt_vf_rep_netdev_ops = {244 .ndo_open = bnxt_vf_rep_open,245 .ndo_stop = bnxt_vf_rep_close,246 .ndo_start_xmit = bnxt_vf_rep_xmit,247 .ndo_get_stats64 = bnxt_vf_rep_get_stats64,248 .ndo_setup_tc = bnxt_vf_rep_setup_tc,249 .ndo_get_port_parent_id = bnxt_vf_rep_get_port_parent_id,250 .ndo_get_phys_port_name = bnxt_vf_rep_get_phys_port_name251};252 253bool bnxt_dev_is_vf_rep(struct net_device *dev)254{255 return dev->netdev_ops == &bnxt_vf_rep_netdev_ops;256}257 258/* Called when the parent PF interface is closed:259 * As the mode transition from SWITCHDEV to LEGACY260 * happens under the rtnl_lock() this routine is safe261 * under the rtnl_lock()262 */263void bnxt_vf_reps_close(struct bnxt *bp)264{265 struct bnxt_vf_rep *vf_rep;266 u16 num_vfs, i;267 268 if (bp->eswitch_mode != DEVLINK_ESWITCH_MODE_SWITCHDEV)269 return;270 271 num_vfs = pci_num_vf(bp->pdev);272 for (i = 0; i < num_vfs; i++) {273 vf_rep = bp->vf_reps[i];274 if (netif_running(vf_rep->dev))275 bnxt_vf_rep_close(vf_rep->dev);276 }277}278 279/* Called when the parent PF interface is opened (re-opened):280 * As the mode transition from SWITCHDEV to LEGACY281 * happen under the rtnl_lock() this routine is safe282 * under the rtnl_lock()283 */284void bnxt_vf_reps_open(struct bnxt *bp)285{286 int i;287 288 if (bp->eswitch_mode != DEVLINK_ESWITCH_MODE_SWITCHDEV)289 return;290 291 for (i = 0; i < pci_num_vf(bp->pdev); i++) {292 /* Open the VF-Rep only if it is allocated in the FW */293 if (bp->vf_reps[i]->tx_cfa_action != CFA_HANDLE_INVALID)294 bnxt_vf_rep_open(bp->vf_reps[i]->dev);295 }296}297 298static void __bnxt_free_one_vf_rep(struct bnxt *bp, struct bnxt_vf_rep *vf_rep)299{300 if (!vf_rep)301 return;302 303 if (vf_rep->dst) {304 dst_release((struct dst_entry *)vf_rep->dst);305 vf_rep->dst = NULL;306 }307 if (vf_rep->tx_cfa_action != CFA_HANDLE_INVALID) {308 hwrm_cfa_vfr_free(bp, vf_rep->vf_idx);309 vf_rep->tx_cfa_action = CFA_HANDLE_INVALID;310 }311}312 313static void __bnxt_vf_reps_destroy(struct bnxt *bp)314{315 u16 num_vfs = pci_num_vf(bp->pdev);316 struct bnxt_vf_rep *vf_rep;317 int i;318 319 for (i = 0; i < num_vfs; i++) {320 vf_rep = bp->vf_reps[i];321 if (vf_rep) {322 __bnxt_free_one_vf_rep(bp, vf_rep);323 if (vf_rep->dev) {324 /* if register_netdev failed, then netdev_ops325 * would have been set to NULL326 */327 if (vf_rep->dev->netdev_ops)328 unregister_netdev(vf_rep->dev);329 free_netdev(vf_rep->dev);330 }331 }332 }333 334 kfree(bp->vf_reps);335 bp->vf_reps = NULL;336}337 338void bnxt_vf_reps_destroy(struct bnxt *bp)339{340 bool closed = false;341 342 if (bp->eswitch_mode != DEVLINK_ESWITCH_MODE_SWITCHDEV)343 return;344 345 if (!bp->vf_reps)346 return;347 348 /* Ensure that parent PF's and VF-reps' RX/TX has been quiesced349 * before proceeding with VF-rep cleanup.350 */351 rtnl_lock();352 if (netif_running(bp->dev)) {353 bnxt_close_nic(bp, false, false);354 closed = true;355 }356 /* un-publish cfa_code_map so that RX path can't see it anymore */357 kfree(bp->cfa_code_map);358 bp->cfa_code_map = NULL;359 360 if (closed) {361 /* Temporarily set legacy mode to avoid re-opening362 * representors and restore switchdev mode after that.363 */364 bp->eswitch_mode = DEVLINK_ESWITCH_MODE_LEGACY;365 bnxt_open_nic(bp, false, false);366 bp->eswitch_mode = DEVLINK_ESWITCH_MODE_SWITCHDEV;367 }368 rtnl_unlock();369 370 /* Need to call vf_reps_destroy() outside of rntl_lock371 * as unregister_netdev takes rtnl_lock372 */373 __bnxt_vf_reps_destroy(bp);374}375 376/* Free the VF-Reps in firmware, during firmware hot-reset processing.377 * Note that the VF-Rep netdevs are still active (not unregistered) during378 * this process. As the mode transition from SWITCHDEV to LEGACY happens379 * under the rtnl_lock() this routine is safe under the rtnl_lock().380 */381void bnxt_vf_reps_free(struct bnxt *bp)382{383 u16 num_vfs = pci_num_vf(bp->pdev);384 int i;385 386 if (bp->eswitch_mode != DEVLINK_ESWITCH_MODE_SWITCHDEV)387 return;388 389 for (i = 0; i < num_vfs; i++)390 __bnxt_free_one_vf_rep(bp, bp->vf_reps[i]);391}392 393static int bnxt_alloc_vf_rep(struct bnxt *bp, struct bnxt_vf_rep *vf_rep,394 u16 *cfa_code_map)395{396 /* get cfa handles from FW */397 if (hwrm_cfa_vfr_alloc(bp, vf_rep->vf_idx, &vf_rep->tx_cfa_action,398 &vf_rep->rx_cfa_code))399 return -ENOLINK;400 401 cfa_code_map[vf_rep->rx_cfa_code] = vf_rep->vf_idx;402 vf_rep->dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX, GFP_KERNEL);403 if (!vf_rep->dst)404 return -ENOMEM;405 406 /* only cfa_action is needed to mux a packet while TXing */407 vf_rep->dst->u.port_info.port_id = vf_rep->tx_cfa_action;408 vf_rep->dst->u.port_info.lower_dev = bp->dev;409 410 return 0;411}412 413/* Allocate the VF-Reps in firmware, during firmware hot-reset processing.414 * Note that the VF-Rep netdevs are still active (not unregistered) during415 * this process. As the mode transition from SWITCHDEV to LEGACY happens416 * under the rtnl_lock() this routine is safe under the rtnl_lock().417 */418int bnxt_vf_reps_alloc(struct bnxt *bp)419{420 u16 *cfa_code_map = bp->cfa_code_map, num_vfs = pci_num_vf(bp->pdev);421 struct bnxt_vf_rep *vf_rep;422 int rc, i;423 424 if (bp->eswitch_mode != DEVLINK_ESWITCH_MODE_SWITCHDEV)425 return 0;426 427 if (!cfa_code_map)428 return -EINVAL;429 430 for (i = 0; i < MAX_CFA_CODE; i++)431 cfa_code_map[i] = VF_IDX_INVALID;432 433 for (i = 0; i < num_vfs; i++) {434 vf_rep = bp->vf_reps[i];435 vf_rep->vf_idx = i;436 437 rc = bnxt_alloc_vf_rep(bp, vf_rep, cfa_code_map);438 if (rc)439 goto err;440 }441 442 return 0;443 444err:445 netdev_info(bp->dev, "%s error=%d\n", __func__, rc);446 bnxt_vf_reps_free(bp);447 return rc;448}449 450/* Use the OUI of the PF's perm addr and report the same mac addr451 * for the same VF-rep each time452 */453static void bnxt_vf_rep_eth_addr_gen(u8 *src_mac, u16 vf_idx, u8 *mac)454{455 u32 addr;456 457 ether_addr_copy(mac, src_mac);458 459 addr = jhash(src_mac, ETH_ALEN, 0) + vf_idx;460 mac[3] = (u8)(addr & 0xFF);461 mac[4] = (u8)((addr >> 8) & 0xFF);462 mac[5] = (u8)((addr >> 16) & 0xFF);463}464 465static void bnxt_vf_rep_netdev_init(struct bnxt *bp, struct bnxt_vf_rep *vf_rep,466 struct net_device *dev)467{468 struct net_device *pf_dev = bp->dev;469 u16 max_mtu;470 471 SET_NETDEV_DEV(dev, &bp->pdev->dev);472 dev->netdev_ops = &bnxt_vf_rep_netdev_ops;473 dev->ethtool_ops = &bnxt_vf_rep_ethtool_ops;474 /* Just inherit all the featues of the parent PF as the VF-R475 * uses the RX/TX rings of the parent PF476 */477 dev->hw_features = pf_dev->hw_features;478 dev->gso_partial_features = pf_dev->gso_partial_features;479 dev->vlan_features = pf_dev->vlan_features;480 dev->hw_enc_features = pf_dev->hw_enc_features;481 dev->features |= pf_dev->features;482 bnxt_vf_rep_eth_addr_gen(bp->pf.mac_addr, vf_rep->vf_idx,483 dev->perm_addr);484 eth_hw_addr_set(dev, dev->perm_addr);485 /* Set VF-Rep's max-mtu to the corresponding VF's max-mtu */486 if (!bnxt_hwrm_vfr_qcfg(bp, vf_rep, &max_mtu))487 dev->max_mtu = max_mtu;488 dev->min_mtu = ETH_ZLEN;489}490 491int bnxt_vf_reps_create(struct bnxt *bp)492{493 u16 *cfa_code_map = NULL, num_vfs = pci_num_vf(bp->pdev);494 struct bnxt_vf_rep *vf_rep;495 struct net_device *dev;496 int rc, i;497 498 if (!(bp->flags & BNXT_FLAG_DSN_VALID))499 return -ENODEV;500 501 bp->vf_reps = kcalloc(num_vfs, sizeof(vf_rep), GFP_KERNEL);502 if (!bp->vf_reps)503 return -ENOMEM;504 505 /* storage for cfa_code to vf-idx mapping */506 cfa_code_map = kmalloc_array(MAX_CFA_CODE, sizeof(*bp->cfa_code_map),507 GFP_KERNEL);508 if (!cfa_code_map) {509 rc = -ENOMEM;510 goto err;511 }512 for (i = 0; i < MAX_CFA_CODE; i++)513 cfa_code_map[i] = VF_IDX_INVALID;514 515 for (i = 0; i < num_vfs; i++) {516 dev = alloc_etherdev(sizeof(*vf_rep));517 if (!dev) {518 rc = -ENOMEM;519 goto err;520 }521 522 vf_rep = netdev_priv(dev);523 bp->vf_reps[i] = vf_rep;524 vf_rep->dev = dev;525 vf_rep->bp = bp;526 vf_rep->vf_idx = i;527 vf_rep->tx_cfa_action = CFA_HANDLE_INVALID;528 529 rc = bnxt_alloc_vf_rep(bp, vf_rep, cfa_code_map);530 if (rc)531 goto err;532 533 bnxt_vf_rep_netdev_init(bp, vf_rep, dev);534 rc = register_netdev(dev);535 if (rc) {536 /* no need for unregister_netdev in cleanup */537 dev->netdev_ops = NULL;538 goto err;539 }540 }541 542 /* publish cfa_code_map only after all VF-reps have been initialized */543 bp->cfa_code_map = cfa_code_map;544 netif_keep_dst(bp->dev);545 return 0;546 547err:548 netdev_info(bp->dev, "%s error=%d\n", __func__, rc);549 kfree(cfa_code_map);550 __bnxt_vf_reps_destroy(bp);551 return rc;552}553 554/* Devlink related routines */555int bnxt_dl_eswitch_mode_get(struct devlink *devlink, u16 *mode)556{557 struct bnxt *bp = bnxt_get_bp_from_dl(devlink);558 559 *mode = bp->eswitch_mode;560 return 0;561}562 563int bnxt_dl_eswitch_mode_set(struct devlink *devlink, u16 mode,564 struct netlink_ext_ack *extack)565{566 struct bnxt *bp = bnxt_get_bp_from_dl(devlink);567 int ret = 0;568 569 if (bp->eswitch_mode == mode) {570 netdev_info(bp->dev, "already in %s eswitch mode\n",571 mode == DEVLINK_ESWITCH_MODE_LEGACY ?572 "legacy" : "switchdev");573 return -EINVAL;574 }575 576 switch (mode) {577 case DEVLINK_ESWITCH_MODE_LEGACY:578 bnxt_vf_reps_destroy(bp);579 break;580 581 case DEVLINK_ESWITCH_MODE_SWITCHDEV:582 if (bp->hwrm_spec_code < 0x10803) {583 netdev_warn(bp->dev, "FW does not support SRIOV E-Switch SWITCHDEV mode\n");584 return -ENOTSUPP;585 }586 587 /* Create representors for existing VFs */588 if (pci_num_vf(bp->pdev) > 0)589 ret = bnxt_vf_reps_create(bp);590 break;591 592 default:593 return -EINVAL;594 }595 596 if (!ret)597 bp->eswitch_mode = mode;598 599 return ret;600}601 602#endif603