]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
bnxt_en: Implement ndo_bridge_{get|set}link methods.
authorMichael Chan <michael.chan@broadcom.com>
Mon, 24 Jul 2017 16:34:22 +0000 (12:34 -0400)
committerChuck Anderson <chuck.anderson@oracle.com>
Wed, 13 Sep 2017 04:41:57 +0000 (21:41 -0700)
Orabug: 26726982

To allow users to set the hardware bridging mode to VEB or VEPA.  Only
single function PF can change the bridging mode.

Signed-off-by: Michael Chan <michael.chan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
(cherry picked from commit 39d8ba2e71fbdde686d7e31ad141a01994dc0793)
Signed-off-by: Brian Maly <brian.maly@oracle.com>
Conflicts:
drivers/net/ethernet/broadcom/bnxt/bnxt.c

drivers/net/ethernet/broadcom/bnxt/bnxt.c

index e4634963029cf397dbb0eb376f93d860038a37f0..5cf4c368366eed9ef5e630880e9349ab09f2ea81 100644 (file)
@@ -4940,6 +4940,26 @@ static void bnxt_hwrm_resource_free(struct bnxt *bp, bool close_path,
        }
 }
 
+static int bnxt_hwrm_set_br_mode(struct bnxt *bp, u16 br_mode)
+{
+       struct hwrm_func_cfg_input req = {0};
+       int rc;
+
+       bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_CFG, -1, -1);
+       req.fid = cpu_to_le16(0xffff);
+       req.enables = cpu_to_le32(FUNC_CFG_REQ_ENABLES_EVB_MODE);
+       if (br_mode == BRIDGE_MODE_VEB)
+               req.evb_mode = FUNC_CFG_REQ_EVB_MODE_VEB;
+       else if (br_mode == BRIDGE_MODE_VEPA)
+               req.evb_mode = FUNC_CFG_REQ_EVB_MODE_VEPA;
+       else
+               return -EINVAL;
+       rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+       if (rc)
+               rc = -EIO;
+       return rc;
+}
+
 static int bnxt_setup_vnic(struct bnxt *bp, u16 vnic_id)
 {
        struct bnxt_vnic_info *vnic = &bp->vnic_info[vnic_id];
@@ -7485,6 +7505,51 @@ static void bnxt_vlan_rx_register(struct net_device *dev,
 }
 #endif
 
+static int bnxt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
+                              struct net_device *dev, u32 filter_mask,
+                              int nlflags)
+{
+       struct bnxt *bp = netdev_priv(dev);
+
+       return ndo_dflt_bridge_getlink(skb, pid, seq, dev, bp->br_mode, 0, 0,
+                                      nlflags);
+}
+
+static int bnxt_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,
+                              u16 flags)
+{
+       struct bnxt *bp = netdev_priv(dev);
+       struct nlattr *attr, *br_spec;
+       int rem, rc = 0;
+
+       if (bp->hwrm_spec_code < 0x10708 || !BNXT_SINGLE_PF(bp))
+               return -EOPNOTSUPP;
+
+       br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
+       if (!br_spec)
+               return -EINVAL;
+
+       nla_for_each_nested(attr, br_spec, rem) {
+               u16 mode;
+
+               if (nla_type(attr) != IFLA_BRIDGE_MODE)
+                       continue;
+
+               if (nla_len(attr) < sizeof(mode))
+                       return -EINVAL;
+
+               mode = nla_get_u16(attr);
+               if (mode == bp->br_mode)
+                       break;
+
+               rc = bnxt_hwrm_set_br_mode(bp, mode);
+               if (!rc)
+                       bp->br_mode = mode;
+               break;
+       }
+       return rc;
+}
+
 static const struct net_device_ops bnxt_netdev_ops = {
        .ndo_open               = bnxt_open,
        .ndo_start_xmit         = bnxt_start_xmit,
@@ -7523,6 +7588,8 @@ static const struct net_device_ops bnxt_netdev_ops = {
        .ndo_add_vxlan_port     = bnxt_add_vxlan_port,
        .ndo_del_vxlan_port     = bnxt_del_vxlan_port,
 #endif
+       .ndo_bridge_getlink     = bnxt_bridge_getlink,
+       .ndo_bridge_setlink     = bnxt_bridge_setlink,
 };
 
 static void bnxt_remove_one(struct pci_dev *pdev)