Back to home page

OSCL-LXR

 
 

    


0001 /* Broadcom NetXtreme-C/E network driver.
0002  *
0003  * Copyright (c) 2016-2017 Broadcom Limited
0004  *
0005  * This program is free software; you can redistribute it and/or modify
0006  * it under the terms of the GNU General Public License as published by
0007  * the Free Software Foundation.
0008  */
0009 #include <linux/pci.h>
0010 #include <linux/netdevice.h>
0011 #include <linux/etherdevice.h>
0012 #include <linux/rtnetlink.h>
0013 #include <linux/jhash.h>
0014 #include <net/pkt_cls.h>
0015 
0016 #include "bnxt_hsi.h"
0017 #include "bnxt.h"
0018 #include "bnxt_hwrm.h"
0019 #include "bnxt_vfr.h"
0020 #include "bnxt_devlink.h"
0021 #include "bnxt_tc.h"
0022 
0023 #ifdef CONFIG_BNXT_SRIOV
0024 
0025 #define CFA_HANDLE_INVALID      0xffff
0026 #define VF_IDX_INVALID          0xffff
0027 
0028 static int hwrm_cfa_vfr_alloc(struct bnxt *bp, u16 vf_idx,
0029                   u16 *tx_cfa_action, u16 *rx_cfa_code)
0030 {
0031     struct hwrm_cfa_vfr_alloc_output *resp;
0032     struct hwrm_cfa_vfr_alloc_input *req;
0033     int rc;
0034 
0035     rc = hwrm_req_init(bp, req, HWRM_CFA_VFR_ALLOC);
0036     if (!rc) {
0037         req->vf_id = cpu_to_le16(vf_idx);
0038         sprintf(req->vfr_name, "vfr%d", vf_idx);
0039 
0040         resp = hwrm_req_hold(bp, req);
0041         rc = hwrm_req_send(bp, req);
0042         if (!rc) {
0043             *tx_cfa_action = le16_to_cpu(resp->tx_cfa_action);
0044             *rx_cfa_code = le16_to_cpu(resp->rx_cfa_code);
0045             netdev_dbg(bp->dev, "tx_cfa_action=0x%x, rx_cfa_code=0x%x",
0046                    *tx_cfa_action, *rx_cfa_code);
0047         }
0048         hwrm_req_drop(bp, req);
0049     }
0050     if (rc)
0051         netdev_info(bp->dev, "%s error rc=%d\n", __func__, rc);
0052     return rc;
0053 }
0054 
0055 static int hwrm_cfa_vfr_free(struct bnxt *bp, u16 vf_idx)
0056 {
0057     struct hwrm_cfa_vfr_free_input *req;
0058     int rc;
0059 
0060     rc = hwrm_req_init(bp, req, HWRM_CFA_VFR_FREE);
0061     if (!rc) {
0062         sprintf(req->vfr_name, "vfr%d", vf_idx);
0063         rc = hwrm_req_send(bp, req);
0064     }
0065     if (rc)
0066         netdev_info(bp->dev, "%s error rc=%d\n", __func__, rc);
0067     return rc;
0068 }
0069 
0070 static int bnxt_hwrm_vfr_qcfg(struct bnxt *bp, struct bnxt_vf_rep *vf_rep,
0071                   u16 *max_mtu)
0072 {
0073     struct hwrm_func_qcfg_output *resp;
0074     struct hwrm_func_qcfg_input *req;
0075     u16 mtu;
0076     int rc;
0077 
0078     rc = hwrm_req_init(bp, req, HWRM_FUNC_QCFG);
0079     if (rc)
0080         return rc;
0081 
0082     req->fid = cpu_to_le16(bp->pf.vf[vf_rep->vf_idx].fw_fid);
0083     resp = hwrm_req_hold(bp, req);
0084     rc = hwrm_req_send(bp, req);
0085     if (!rc) {
0086         mtu = le16_to_cpu(resp->max_mtu_configured);
0087         if (!mtu)
0088             *max_mtu = BNXT_MAX_MTU;
0089         else
0090             *max_mtu = mtu;
0091     }
0092     hwrm_req_drop(bp, req);
0093     return rc;
0094 }
0095 
0096 static int bnxt_vf_rep_open(struct net_device *dev)
0097 {
0098     struct bnxt_vf_rep *vf_rep = netdev_priv(dev);
0099     struct bnxt *bp = vf_rep->bp;
0100 
0101     /* Enable link and TX only if the parent PF is open. */
0102     if (netif_running(bp->dev)) {
0103         netif_carrier_on(dev);
0104         netif_tx_start_all_queues(dev);
0105     }
0106     return 0;
0107 }
0108 
0109 static int bnxt_vf_rep_close(struct net_device *dev)
0110 {
0111     netif_carrier_off(dev);
0112     netif_tx_disable(dev);
0113 
0114     return 0;
0115 }
0116 
0117 static netdev_tx_t bnxt_vf_rep_xmit(struct sk_buff *skb,
0118                     struct net_device *dev)
0119 {
0120     struct bnxt_vf_rep *vf_rep = netdev_priv(dev);
0121     int rc, len = skb->len;
0122 
0123     skb_dst_drop(skb);
0124     dst_hold((struct dst_entry *)vf_rep->dst);
0125     skb_dst_set(skb, (struct dst_entry *)vf_rep->dst);
0126     skb->dev = vf_rep->dst->u.port_info.lower_dev;
0127 
0128     rc = dev_queue_xmit(skb);
0129     if (!rc) {
0130         vf_rep->tx_stats.packets++;
0131         vf_rep->tx_stats.bytes += len;
0132     }
0133     return rc;
0134 }
0135 
0136 static void
0137 bnxt_vf_rep_get_stats64(struct net_device *dev,
0138             struct rtnl_link_stats64 *stats)
0139 {
0140     struct bnxt_vf_rep *vf_rep = netdev_priv(dev);
0141 
0142     stats->rx_packets = vf_rep->rx_stats.packets;
0143     stats->rx_bytes = vf_rep->rx_stats.bytes;
0144     stats->tx_packets = vf_rep->tx_stats.packets;
0145     stats->tx_bytes = vf_rep->tx_stats.bytes;
0146 }
0147 
0148 static int bnxt_vf_rep_setup_tc_block_cb(enum tc_setup_type type,
0149                      void *type_data,
0150                      void *cb_priv)
0151 {
0152     struct bnxt_vf_rep *vf_rep = cb_priv;
0153     struct bnxt *bp = vf_rep->bp;
0154     int vf_fid = bp->pf.vf[vf_rep->vf_idx].fw_fid;
0155 
0156     if (!bnxt_tc_flower_enabled(vf_rep->bp) ||
0157         !tc_cls_can_offload_and_chain0(bp->dev, type_data))
0158         return -EOPNOTSUPP;
0159 
0160     switch (type) {
0161     case TC_SETUP_CLSFLOWER:
0162         return bnxt_tc_setup_flower(bp, vf_fid, type_data);
0163     default:
0164         return -EOPNOTSUPP;
0165     }
0166 }
0167 
0168 static LIST_HEAD(bnxt_vf_block_cb_list);
0169 
0170 static int bnxt_vf_rep_setup_tc(struct net_device *dev, enum tc_setup_type type,
0171                 void *type_data)
0172 {
0173     struct bnxt_vf_rep *vf_rep = netdev_priv(dev);
0174 
0175     switch (type) {
0176     case TC_SETUP_BLOCK:
0177         return flow_block_cb_setup_simple(type_data,
0178                           &bnxt_vf_block_cb_list,
0179                           bnxt_vf_rep_setup_tc_block_cb,
0180                           vf_rep, vf_rep, true);
0181     default:
0182         return -EOPNOTSUPP;
0183     }
0184 }
0185 
0186 struct net_device *bnxt_get_vf_rep(struct bnxt *bp, u16 cfa_code)
0187 {
0188     u16 vf_idx;
0189 
0190     if (cfa_code && bp->cfa_code_map && BNXT_PF(bp)) {
0191         vf_idx = bp->cfa_code_map[cfa_code];
0192         if (vf_idx != VF_IDX_INVALID)
0193             return bp->vf_reps[vf_idx]->dev;
0194     }
0195     return NULL;
0196 }
0197 
0198 void bnxt_vf_rep_rx(struct bnxt *bp, struct sk_buff *skb)
0199 {
0200     struct bnxt_vf_rep *vf_rep = netdev_priv(skb->dev);
0201 
0202     vf_rep->rx_stats.bytes += skb->len;
0203     vf_rep->rx_stats.packets++;
0204 
0205     netif_receive_skb(skb);
0206 }
0207 
0208 static int bnxt_vf_rep_get_phys_port_name(struct net_device *dev, char *buf,
0209                       size_t len)
0210 {
0211     struct bnxt_vf_rep *vf_rep = netdev_priv(dev);
0212     struct pci_dev *pf_pdev = vf_rep->bp->pdev;
0213     int rc;
0214 
0215     rc = snprintf(buf, len, "pf%dvf%d", PCI_FUNC(pf_pdev->devfn),
0216               vf_rep->vf_idx);
0217     if (rc >= len)
0218         return -EOPNOTSUPP;
0219     return 0;
0220 }
0221 
0222 static void bnxt_vf_rep_get_drvinfo(struct net_device *dev,
0223                     struct ethtool_drvinfo *info)
0224 {
0225     strlcpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
0226 }
0227 
0228 static int bnxt_vf_rep_get_port_parent_id(struct net_device *dev,
0229                       struct netdev_phys_item_id *ppid)
0230 {
0231     struct bnxt_vf_rep *vf_rep = netdev_priv(dev);
0232 
0233     /* as only PORT_PARENT_ID is supported currently use common code
0234      * between PF and VF-rep for now.
0235      */
0236     return bnxt_get_port_parent_id(vf_rep->bp->dev, ppid);
0237 }
0238 
0239 static const struct ethtool_ops bnxt_vf_rep_ethtool_ops = {
0240     .get_drvinfo        = bnxt_vf_rep_get_drvinfo
0241 };
0242 
0243 static const struct net_device_ops bnxt_vf_rep_netdev_ops = {
0244     .ndo_open       = bnxt_vf_rep_open,
0245     .ndo_stop       = bnxt_vf_rep_close,
0246     .ndo_start_xmit     = bnxt_vf_rep_xmit,
0247     .ndo_get_stats64    = bnxt_vf_rep_get_stats64,
0248     .ndo_setup_tc       = bnxt_vf_rep_setup_tc,
0249     .ndo_get_port_parent_id = bnxt_vf_rep_get_port_parent_id,
0250     .ndo_get_phys_port_name = bnxt_vf_rep_get_phys_port_name
0251 };
0252 
0253 bool bnxt_dev_is_vf_rep(struct net_device *dev)
0254 {
0255     return dev->netdev_ops == &bnxt_vf_rep_netdev_ops;
0256 }
0257 
0258 /* Called when the parent PF interface is closed:
0259  * As the mode transition from SWITCHDEV to LEGACY
0260  * happens under the rtnl_lock() this routine is safe
0261  * under the rtnl_lock()
0262  */
0263 void bnxt_vf_reps_close(struct bnxt *bp)
0264 {
0265     struct bnxt_vf_rep *vf_rep;
0266     u16 num_vfs, i;
0267 
0268     if (bp->eswitch_mode != DEVLINK_ESWITCH_MODE_SWITCHDEV)
0269         return;
0270 
0271     num_vfs = pci_num_vf(bp->pdev);
0272     for (i = 0; i < num_vfs; i++) {
0273         vf_rep = bp->vf_reps[i];
0274         if (netif_running(vf_rep->dev))
0275             bnxt_vf_rep_close(vf_rep->dev);
0276     }
0277 }
0278 
0279 /* Called when the parent PF interface is opened (re-opened):
0280  * As the mode transition from SWITCHDEV to LEGACY
0281  * happen under the rtnl_lock() this routine is safe
0282  * under the rtnl_lock()
0283  */
0284 void bnxt_vf_reps_open(struct bnxt *bp)
0285 {
0286     int i;
0287 
0288     if (bp->eswitch_mode != DEVLINK_ESWITCH_MODE_SWITCHDEV)
0289         return;
0290 
0291     for (i = 0; i < pci_num_vf(bp->pdev); i++) {
0292         /* Open the VF-Rep only if it is allocated in the FW */
0293         if (bp->vf_reps[i]->tx_cfa_action != CFA_HANDLE_INVALID)
0294             bnxt_vf_rep_open(bp->vf_reps[i]->dev);
0295     }
0296 }
0297 
0298 static void __bnxt_free_one_vf_rep(struct bnxt *bp, struct bnxt_vf_rep *vf_rep)
0299 {
0300     if (!vf_rep)
0301         return;
0302 
0303     if (vf_rep->dst) {
0304         dst_release((struct dst_entry *)vf_rep->dst);
0305         vf_rep->dst = NULL;
0306     }
0307     if (vf_rep->tx_cfa_action != CFA_HANDLE_INVALID) {
0308         hwrm_cfa_vfr_free(bp, vf_rep->vf_idx);
0309         vf_rep->tx_cfa_action = CFA_HANDLE_INVALID;
0310     }
0311 }
0312 
0313 static void __bnxt_vf_reps_destroy(struct bnxt *bp)
0314 {
0315     u16 num_vfs = pci_num_vf(bp->pdev);
0316     struct bnxt_vf_rep *vf_rep;
0317     int i;
0318 
0319     for (i = 0; i < num_vfs; i++) {
0320         vf_rep = bp->vf_reps[i];
0321         if (vf_rep) {
0322             __bnxt_free_one_vf_rep(bp, vf_rep);
0323             if (vf_rep->dev) {
0324                 /* if register_netdev failed, then netdev_ops
0325                  * would have been set to NULL
0326                  */
0327                 if (vf_rep->dev->netdev_ops)
0328                     unregister_netdev(vf_rep->dev);
0329                 free_netdev(vf_rep->dev);
0330             }
0331         }
0332     }
0333 
0334     kfree(bp->vf_reps);
0335     bp->vf_reps = NULL;
0336 }
0337 
0338 void bnxt_vf_reps_destroy(struct bnxt *bp)
0339 {
0340     bool closed = false;
0341 
0342     if (bp->eswitch_mode != DEVLINK_ESWITCH_MODE_SWITCHDEV)
0343         return;
0344 
0345     if (!bp->vf_reps)
0346         return;
0347 
0348     /* Ensure that parent PF's and VF-reps' RX/TX has been quiesced
0349      * before proceeding with VF-rep cleanup.
0350      */
0351     rtnl_lock();
0352     if (netif_running(bp->dev)) {
0353         bnxt_close_nic(bp, false, false);
0354         closed = true;
0355     }
0356     /* un-publish cfa_code_map so that RX path can't see it anymore */
0357     kfree(bp->cfa_code_map);
0358     bp->cfa_code_map = NULL;
0359     bp->eswitch_mode = DEVLINK_ESWITCH_MODE_LEGACY;
0360 
0361     if (closed)
0362         bnxt_open_nic(bp, false, false);
0363     rtnl_unlock();
0364 
0365     /* Need to call vf_reps_destroy() outside of rntl_lock
0366      * as unregister_netdev takes rtnl_lock
0367      */
0368     __bnxt_vf_reps_destroy(bp);
0369 }
0370 
0371 /* Free the VF-Reps in firmware, during firmware hot-reset processing.
0372  * Note that the VF-Rep netdevs are still active (not unregistered) during
0373  * this process. As the mode transition from SWITCHDEV to LEGACY happens
0374  * under the rtnl_lock() this routine is safe under the rtnl_lock().
0375  */
0376 void bnxt_vf_reps_free(struct bnxt *bp)
0377 {
0378     u16 num_vfs = pci_num_vf(bp->pdev);
0379     int i;
0380 
0381     if (bp->eswitch_mode != DEVLINK_ESWITCH_MODE_SWITCHDEV)
0382         return;
0383 
0384     for (i = 0; i < num_vfs; i++)
0385         __bnxt_free_one_vf_rep(bp, bp->vf_reps[i]);
0386 }
0387 
0388 static int bnxt_alloc_vf_rep(struct bnxt *bp, struct bnxt_vf_rep *vf_rep,
0389                  u16 *cfa_code_map)
0390 {
0391     /* get cfa handles from FW */
0392     if (hwrm_cfa_vfr_alloc(bp, vf_rep->vf_idx, &vf_rep->tx_cfa_action,
0393                    &vf_rep->rx_cfa_code))
0394         return -ENOLINK;
0395 
0396     cfa_code_map[vf_rep->rx_cfa_code] = vf_rep->vf_idx;
0397     vf_rep->dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX, GFP_KERNEL);
0398     if (!vf_rep->dst)
0399         return -ENOMEM;
0400 
0401     /* only cfa_action is needed to mux a packet while TXing */
0402     vf_rep->dst->u.port_info.port_id = vf_rep->tx_cfa_action;
0403     vf_rep->dst->u.port_info.lower_dev = bp->dev;
0404 
0405     return 0;
0406 }
0407 
0408 /* Allocate the VF-Reps in firmware, during firmware hot-reset processing.
0409  * Note that the VF-Rep netdevs are still active (not unregistered) during
0410  * this process. As the mode transition from SWITCHDEV to LEGACY happens
0411  * under the rtnl_lock() this routine is safe under the rtnl_lock().
0412  */
0413 int bnxt_vf_reps_alloc(struct bnxt *bp)
0414 {
0415     u16 *cfa_code_map = bp->cfa_code_map, num_vfs = pci_num_vf(bp->pdev);
0416     struct bnxt_vf_rep *vf_rep;
0417     int rc, i;
0418 
0419     if (bp->eswitch_mode != DEVLINK_ESWITCH_MODE_SWITCHDEV)
0420         return 0;
0421 
0422     if (!cfa_code_map)
0423         return -EINVAL;
0424 
0425     for (i = 0; i < MAX_CFA_CODE; i++)
0426         cfa_code_map[i] = VF_IDX_INVALID;
0427 
0428     for (i = 0; i < num_vfs; i++) {
0429         vf_rep = bp->vf_reps[i];
0430         vf_rep->vf_idx = i;
0431 
0432         rc = bnxt_alloc_vf_rep(bp, vf_rep, cfa_code_map);
0433         if (rc)
0434             goto err;
0435     }
0436 
0437     return 0;
0438 
0439 err:
0440     netdev_info(bp->dev, "%s error=%d\n", __func__, rc);
0441     bnxt_vf_reps_free(bp);
0442     return rc;
0443 }
0444 
0445 /* Use the OUI of the PF's perm addr and report the same mac addr
0446  * for the same VF-rep each time
0447  */
0448 static void bnxt_vf_rep_eth_addr_gen(u8 *src_mac, u16 vf_idx, u8 *mac)
0449 {
0450     u32 addr;
0451 
0452     ether_addr_copy(mac, src_mac);
0453 
0454     addr = jhash(src_mac, ETH_ALEN, 0) + vf_idx;
0455     mac[3] = (u8)(addr & 0xFF);
0456     mac[4] = (u8)((addr >> 8) & 0xFF);
0457     mac[5] = (u8)((addr >> 16) & 0xFF);
0458 }
0459 
0460 static void bnxt_vf_rep_netdev_init(struct bnxt *bp, struct bnxt_vf_rep *vf_rep,
0461                     struct net_device *dev)
0462 {
0463     struct net_device *pf_dev = bp->dev;
0464     u16 max_mtu;
0465 
0466     dev->netdev_ops = &bnxt_vf_rep_netdev_ops;
0467     dev->ethtool_ops = &bnxt_vf_rep_ethtool_ops;
0468     /* Just inherit all the featues of the parent PF as the VF-R
0469      * uses the RX/TX rings of the parent PF
0470      */
0471     dev->hw_features = pf_dev->hw_features;
0472     dev->gso_partial_features = pf_dev->gso_partial_features;
0473     dev->vlan_features = pf_dev->vlan_features;
0474     dev->hw_enc_features = pf_dev->hw_enc_features;
0475     dev->features |= pf_dev->features;
0476     bnxt_vf_rep_eth_addr_gen(bp->pf.mac_addr, vf_rep->vf_idx,
0477                  dev->perm_addr);
0478     eth_hw_addr_set(dev, dev->perm_addr);
0479     /* Set VF-Rep's max-mtu to the corresponding VF's max-mtu */
0480     if (!bnxt_hwrm_vfr_qcfg(bp, vf_rep, &max_mtu))
0481         dev->max_mtu = max_mtu;
0482     dev->min_mtu = ETH_ZLEN;
0483 }
0484 
0485 static int bnxt_vf_reps_create(struct bnxt *bp)
0486 {
0487     u16 *cfa_code_map = NULL, num_vfs = pci_num_vf(bp->pdev);
0488     struct bnxt_vf_rep *vf_rep;
0489     struct net_device *dev;
0490     int rc, i;
0491 
0492     if (!(bp->flags & BNXT_FLAG_DSN_VALID))
0493         return -ENODEV;
0494 
0495     bp->vf_reps = kcalloc(num_vfs, sizeof(vf_rep), GFP_KERNEL);
0496     if (!bp->vf_reps)
0497         return -ENOMEM;
0498 
0499     /* storage for cfa_code to vf-idx mapping */
0500     cfa_code_map = kmalloc_array(MAX_CFA_CODE, sizeof(*bp->cfa_code_map),
0501                      GFP_KERNEL);
0502     if (!cfa_code_map) {
0503         rc = -ENOMEM;
0504         goto err;
0505     }
0506     for (i = 0; i < MAX_CFA_CODE; i++)
0507         cfa_code_map[i] = VF_IDX_INVALID;
0508 
0509     for (i = 0; i < num_vfs; i++) {
0510         dev = alloc_etherdev(sizeof(*vf_rep));
0511         if (!dev) {
0512             rc = -ENOMEM;
0513             goto err;
0514         }
0515 
0516         vf_rep = netdev_priv(dev);
0517         bp->vf_reps[i] = vf_rep;
0518         vf_rep->dev = dev;
0519         vf_rep->bp = bp;
0520         vf_rep->vf_idx = i;
0521         vf_rep->tx_cfa_action = CFA_HANDLE_INVALID;
0522 
0523         rc = bnxt_alloc_vf_rep(bp, vf_rep, cfa_code_map);
0524         if (rc)
0525             goto err;
0526 
0527         bnxt_vf_rep_netdev_init(bp, vf_rep, dev);
0528         rc = register_netdev(dev);
0529         if (rc) {
0530             /* no need for unregister_netdev in cleanup */
0531             dev->netdev_ops = NULL;
0532             goto err;
0533         }
0534     }
0535 
0536     /* publish cfa_code_map only after all VF-reps have been initialized */
0537     bp->cfa_code_map = cfa_code_map;
0538     bp->eswitch_mode = DEVLINK_ESWITCH_MODE_SWITCHDEV;
0539     netif_keep_dst(bp->dev);
0540     return 0;
0541 
0542 err:
0543     netdev_info(bp->dev, "%s error=%d\n", __func__, rc);
0544     kfree(cfa_code_map);
0545     __bnxt_vf_reps_destroy(bp);
0546     return rc;
0547 }
0548 
0549 /* Devlink related routines */
0550 int bnxt_dl_eswitch_mode_get(struct devlink *devlink, u16 *mode)
0551 {
0552     struct bnxt *bp = bnxt_get_bp_from_dl(devlink);
0553 
0554     *mode = bp->eswitch_mode;
0555     return 0;
0556 }
0557 
0558 int bnxt_dl_eswitch_mode_set(struct devlink *devlink, u16 mode,
0559                  struct netlink_ext_ack *extack)
0560 {
0561     struct bnxt *bp = bnxt_get_bp_from_dl(devlink);
0562 
0563     if (bp->eswitch_mode == mode) {
0564         netdev_info(bp->dev, "already in %s eswitch mode\n",
0565                 mode == DEVLINK_ESWITCH_MODE_LEGACY ?
0566                 "legacy" : "switchdev");
0567         return -EINVAL;
0568     }
0569 
0570     switch (mode) {
0571     case DEVLINK_ESWITCH_MODE_LEGACY:
0572         bnxt_vf_reps_destroy(bp);
0573         return 0;
0574 
0575     case DEVLINK_ESWITCH_MODE_SWITCHDEV:
0576         if (bp->hwrm_spec_code < 0x10803) {
0577             netdev_warn(bp->dev, "FW does not support SRIOV E-Switch SWITCHDEV mode\n");
0578             return -ENOTSUPP;
0579         }
0580 
0581         if (pci_num_vf(bp->pdev) == 0) {
0582             netdev_info(bp->dev, "Enable VFs before setting switchdev mode\n");
0583             return -EPERM;
0584         }
0585         return bnxt_vf_reps_create(bp);
0586 
0587     default:
0588         return -EINVAL;
0589     }
0590 }
0591 
0592 #endif