bnxt_en: add support for port_attr_get and and get_phys_port_name
authorSathya Perla <sathya.perla@broadcom.com>
Mon, 24 Jul 2017 16:34:29 +0000 (12:34 -0400)
committerDavid S. Miller <davem@davemloft.net>
Tue, 25 Jul 2017 00:29:58 +0000 (17:29 -0700)
This patch adds support for the switchdev_port_attr_get() and
ndo_get_phys_port_name() methods for the PF and the VF-reps.
Using this support a user application can deduce that the PF
(when in the ESWITCH_SWDEV mode) and it's VF-reps form a switch.

Signed-off-by: Sathya Perla <sathya.perla@broadcom.com>
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt.h
drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c

index f262fe6092d7795a430d5649b2e8561e1b921716..82cbe1804821abd3bad051fb5146142942533fe4 100644 (file)
@@ -7546,6 +7546,61 @@ static int bnxt_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,
        return rc;
 }
 
+static int bnxt_get_phys_port_name(struct net_device *dev, char *buf,
+                                  size_t len)
+{
+       struct bnxt *bp = netdev_priv(dev);
+       int rc;
+
+       /* The PF and it's VF-reps only support the switchdev framework */
+       if (!BNXT_PF(bp))
+               return -EOPNOTSUPP;
+
+       /* The switch-id that the pf belongs to is exported by
+        * the switchdev ndo. This name is just to distinguish from the
+        * vf-rep ports.
+        */
+       rc = snprintf(buf, len, "pf%d", bp->pf.port_id);
+
+       if (rc >= len)
+               return -EOPNOTSUPP;
+       return 0;
+}
+
+int bnxt_port_attr_get(struct bnxt *bp, struct switchdev_attr *attr)
+{
+       if (bp->eswitch_mode != DEVLINK_ESWITCH_MODE_SWITCHDEV)
+               return -EOPNOTSUPP;
+
+       /* The PF and it's VF-reps only support the switchdev framework */
+       if (!BNXT_PF(bp))
+               return -EOPNOTSUPP;
+
+       switch (attr->id) {
+       case SWITCHDEV_ATTR_ID_PORT_PARENT_ID:
+               /* In SRIOV each PF-pool (PF + child VFs) serves as a
+                * switching domain, the PF's perm mac-addr can be used
+                * as the unique parent-id
+                */
+               attr->u.ppid.id_len = ETH_ALEN;
+               ether_addr_copy(attr->u.ppid.id, bp->pf.mac_addr);
+               break;
+       default:
+               return -EOPNOTSUPP;
+       }
+       return 0;
+}
+
+static int bnxt_swdev_port_attr_get(struct net_device *dev,
+                                   struct switchdev_attr *attr)
+{
+       return bnxt_port_attr_get(netdev_priv(dev), attr);
+}
+
+static const struct switchdev_ops bnxt_switchdev_ops = {
+       .switchdev_port_attr_get        = bnxt_swdev_port_attr_get
+};
+
 static const struct net_device_ops bnxt_netdev_ops = {
        .ndo_open               = bnxt_open,
        .ndo_start_xmit         = bnxt_start_xmit,
@@ -7579,6 +7634,7 @@ static const struct net_device_ops bnxt_netdev_ops = {
        .ndo_xdp                = bnxt_xdp,
        .ndo_bridge_getlink     = bnxt_bridge_getlink,
        .ndo_bridge_setlink     = bnxt_bridge_setlink,
+       .ndo_get_phys_port_name = bnxt_get_phys_port_name
 };
 
 static void bnxt_remove_one(struct pci_dev *pdev)
@@ -7838,6 +7894,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        dev->netdev_ops = &bnxt_netdev_ops;
        dev->watchdog_timeo = BNXT_TX_TIMEOUT;
        dev->ethtool_ops = &bnxt_ethtool_ops;
+       dev->switchdev_ops = &bnxt_switchdev_ops;
        pci_set_drvdata(pdev, dev);
 
        rc = bnxt_alloc_hwrm_resources(bp);
index 63756f0389d71e1d5ebe20cdef66661ef1aa40ed..2d84d5719b701893e0f615fb7c542f31b5ba25a5 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/interrupt.h>
 #include <net/devlink.h>
 #include <net/dst_metadata.h>
+#include <net/switchdev.h>
 
 struct tx_bd {
        __le32 tx_bd_len_flags_type;
@@ -1350,4 +1351,5 @@ int bnxt_reserve_rings(struct bnxt *bp, int tx, int rx, bool sh, int tcs,
 int bnxt_setup_mq_tc(struct net_device *dev, u8 tc);
 int bnxt_get_max_rings(struct bnxt *, int *, int *, bool);
 void bnxt_restore_pf_fw_resources(struct bnxt *bp);
+int bnxt_port_attr_get(struct bnxt *bp, struct switchdev_attr *attr);
 #endif
index 60bdb181358e17baa53f8c5f29f8c739b205f644..83478e912ee5ba6808d4cf69433c641049e82329 100644 (file)
@@ -135,6 +135,18 @@ void bnxt_vf_rep_rx(struct bnxt *bp, struct sk_buff *skb)
        netif_receive_skb(skb);
 }
 
+static int bnxt_vf_rep_get_phys_port_name(struct net_device *dev, char *buf,
+                                         size_t len)
+{
+       struct bnxt_vf_rep *vf_rep = netdev_priv(dev);
+       int rc;
+
+       rc = snprintf(buf, len, "vfr%d", vf_rep->vf_idx);
+       if (rc >= len)
+               return -EOPNOTSUPP;
+       return 0;
+}
+
 static void bnxt_vf_rep_get_drvinfo(struct net_device *dev,
                                    struct ethtool_drvinfo *info)
 {
@@ -142,6 +154,21 @@ static void bnxt_vf_rep_get_drvinfo(struct net_device *dev,
        strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version));
 }
 
+static int bnxt_vf_rep_port_attr_get(struct net_device *dev,
+                                    struct switchdev_attr *attr)
+{
+       struct bnxt_vf_rep *vf_rep = netdev_priv(dev);
+
+       /* as only PORT_PARENT_ID is supported currently use common code
+        * between PF and VF-rep for now.
+        */
+       return bnxt_port_attr_get(vf_rep->bp, attr);
+}
+
+static const struct switchdev_ops bnxt_vf_rep_switchdev_ops = {
+       .switchdev_port_attr_get        = bnxt_vf_rep_port_attr_get
+};
+
 static const struct ethtool_ops bnxt_vf_rep_ethtool_ops = {
        .get_drvinfo            = bnxt_vf_rep_get_drvinfo
 };
@@ -150,7 +177,8 @@ static const struct net_device_ops bnxt_vf_rep_netdev_ops = {
        .ndo_open               = bnxt_vf_rep_open,
        .ndo_stop               = bnxt_vf_rep_close,
        .ndo_start_xmit         = bnxt_vf_rep_xmit,
-       .ndo_get_stats64        = bnxt_vf_rep_get_stats64
+       .ndo_get_stats64        = bnxt_vf_rep_get_stats64,
+       .ndo_get_phys_port_name = bnxt_vf_rep_get_phys_port_name
 };
 
 /* Called when the parent PF interface is closed:
@@ -274,6 +302,7 @@ static void bnxt_vf_rep_netdev_init(struct bnxt *bp, struct bnxt_vf_rep *vf_rep,
 
        dev->netdev_ops = &bnxt_vf_rep_netdev_ops;
        dev->ethtool_ops = &bnxt_vf_rep_ethtool_ops;
+       dev->switchdev_ops = &bnxt_vf_rep_switchdev_ops;
        /* Just inherit all the featues of the parent PF as the VF-R
         * uses the RX/TX rings of the parent PF
         */