]> Pileus Git - ~andy/linux/blobdiff - drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
ixgbe: enable devices with internal switch to read pci parent
[~andy/linux] / drivers / net / ethernet / intel / ixgbe / ixgbe_main.c
index db5611ae407ed5ec3a2c90341e96c12e6945ff9d..3beac23006433bc31d73cf8f0cd3a456e607bae5 100644 (file)
@@ -149,6 +149,52 @@ MODULE_DESCRIPTION("Intel(R) 10 Gigabit PCI Express Network Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 
+static int ixgbe_read_pci_cfg_word_parent(struct ixgbe_adapter *adapter,
+                                         u32 reg, u16 *value)
+{
+       int pos = 0;
+       struct pci_dev *parent_dev;
+       struct pci_bus *parent_bus;
+
+       parent_bus = adapter->pdev->bus->parent;
+       if (!parent_bus)
+               return -1;
+
+       parent_dev = parent_bus->self;
+       if (!parent_dev)
+               return -1;
+
+       pos = pci_find_capability(parent_dev, PCI_CAP_ID_EXP);
+       if (!pos)
+               return -1;
+
+       pci_read_config_word(parent_dev, pos + reg, value);
+       return 0;
+}
+
+static s32 ixgbe_get_parent_bus_info(struct ixgbe_adapter *adapter)
+{
+       struct ixgbe_hw *hw = &adapter->hw;
+       u16 link_status = 0;
+       int err;
+
+       hw->bus.type = ixgbe_bus_type_pci_express;
+
+       /* Get the negotiated link width and speed from PCI config space of the
+        * parent, as this device is behind a switch
+        */
+       err = ixgbe_read_pci_cfg_word_parent(adapter, 18, &link_status);
+
+       /* assume caller will handle error case */
+       if (err)
+               return err;
+
+       hw->bus.width = ixgbe_convert_bus_width(link_status);
+       hw->bus.speed = ixgbe_convert_bus_speed(link_status);
+
+       return 0;
+}
+
 static void ixgbe_service_event_schedule(struct ixgbe_adapter *adapter)
 {
        if (!test_bit(__IXGBE_DOWN, &adapter->state) &&
@@ -1337,7 +1383,7 @@ static unsigned int ixgbe_get_headlen(unsigned char *data,
                        return hdr.network - data;
 
                /* record next protocol if header is present */
-               if (!hdr.ipv4->frag_off)
+               if (!(hdr.ipv4->frag_off & htons(IP_OFFSET)))
                        nexthdr = hdr.ipv4->protocol;
        } else if (protocol == __constant_htons(ETH_P_IPV6)) {
                if ((hdr.network - data) > (max_len - sizeof(struct ipv6hdr)))
@@ -6425,9 +6471,7 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
        struct ixgbe_tx_buffer *first;
        int tso;
        u32 tx_flags = 0;
-#if PAGE_SIZE > IXGBE_MAX_DATA_PER_TXD
        unsigned short f;
-#endif
        u16 count = TXD_USE_COUNT(skb_headlen(skb));
        __be16 protocol = skb->protocol;
        u8 hdr_len = 0;
@@ -6439,12 +6483,9 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
         *       + 1 desc for context descriptor,
         * otherwise try next time
         */
-#if PAGE_SIZE > IXGBE_MAX_DATA_PER_TXD
        for (f = 0; f < skb_shinfo(skb)->nr_frags; f++)
                count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size);
-#else
-       count += skb_shinfo(skb)->nr_frags;
-#endif
+
        if (ixgbe_maybe_stop_tx(tx_ring, count + 3)) {
                tx_ring->tx_stats.tx_busy++;
                return NETDEV_TX_BUSY;
@@ -7007,7 +7048,7 @@ static int ixgbe_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
        int err;
 
        if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED))
-               return -EOPNOTSUPP;
+               return ndo_dflt_fdb_add(ndm, tb, dev, addr, flags);
 
        /* Hardware does not support aging addresses so if a
         * ndm_state is given only allow permanent addresses
@@ -7038,44 +7079,6 @@ static int ixgbe_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
        return err;
 }
 
-static int ixgbe_ndo_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
-                            struct net_device *dev,
-                            const unsigned char *addr)
-{
-       struct ixgbe_adapter *adapter = netdev_priv(dev);
-       int err = -EOPNOTSUPP;
-
-       if (ndm->ndm_state & NUD_PERMANENT) {
-               pr_info("%s: FDB only supports static addresses\n",
-                       ixgbe_driver_name);
-               return -EINVAL;
-       }
-
-       if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) {
-               if (is_unicast_ether_addr(addr))
-                       err = dev_uc_del(dev, addr);
-               else if (is_multicast_ether_addr(addr))
-                       err = dev_mc_del(dev, addr);
-               else
-                       err = -EINVAL;
-       }
-
-       return err;
-}
-
-static int ixgbe_ndo_fdb_dump(struct sk_buff *skb,
-                             struct netlink_callback *cb,
-                             struct net_device *dev,
-                             int idx)
-{
-       struct ixgbe_adapter *adapter = netdev_priv(dev);
-
-       if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
-               idx = ndo_dflt_fdb_dump(skb, cb, dev, idx);
-
-       return idx;
-}
-
 static int ixgbe_ndo_bridge_setlink(struct net_device *dev,
                                    struct nlmsghdr *nlh)
 {
@@ -7171,8 +7174,6 @@ static const struct net_device_ops ixgbe_netdev_ops = {
        .ndo_set_features = ixgbe_set_features,
        .ndo_fix_features = ixgbe_fix_features,
        .ndo_fdb_add            = ixgbe_ndo_fdb_add,
-       .ndo_fdb_del            = ixgbe_ndo_fdb_del,
-       .ndo_fdb_dump           = ixgbe_ndo_fdb_dump,
        .ndo_bridge_setlink     = ixgbe_ndo_bridge_setlink,
        .ndo_bridge_getlink     = ixgbe_ndo_bridge_getlink,
 };
@@ -7532,10 +7533,13 @@ skip_sriov:
 
        /* pick up the PCI bus settings for reporting later */
        hw->mac.ops.get_bus_info(hw);
+       if (hw->device_id == IXGBE_DEV_ID_82599_SFP_SF_QP)
+               ixgbe_get_parent_bus_info(adapter);
 
        /* print bus type/speed/width info */
        e_dev_info("(PCI Express:%s:%s) %pM\n",
-                  (hw->bus.speed == ixgbe_bus_speed_5000 ? "5.0GT/s" :
+                  (hw->bus.speed == ixgbe_bus_speed_8000 ? "8.0GT/s" :
+                   hw->bus.speed == ixgbe_bus_speed_5000 ? "5.0GT/s" :
                    hw->bus.speed == ixgbe_bus_speed_2500 ? "2.5GT/s" :
                    "Unknown"),
                   (hw->bus.width == ixgbe_bus_width_pcie_x8 ? "Width x8" :
@@ -7922,12 +7926,19 @@ static int __init ixgbe_init_module(void)
        ixgbe_dbg_init();
 #endif /* CONFIG_DEBUG_FS */
 
+       ret = pci_register_driver(&ixgbe_driver);
+       if (ret) {
+#ifdef CONFIG_DEBUG_FS
+               ixgbe_dbg_exit();
+#endif /* CONFIG_DEBUG_FS */
+               return ret;
+       }
+
 #ifdef CONFIG_IXGBE_DCA
        dca_register_notify(&dca_notifier);
 #endif
 
-       ret = pci_register_driver(&ixgbe_driver);
-       return ret;
+       return 0;
 }
 
 module_init(ixgbe_init_module);