]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-next
authorDavid S. Miller <davem@davemloft.net>
Tue, 18 Oct 2011 00:21:50 +0000 (20:21 -0400)
committerDavid S. Miller <davem@davemloft.net>
Tue, 18 Oct 2011 00:21:50 +0000 (20:21 -0400)
drivers/net/ethernet/intel/igb/igb.h
drivers/net/ethernet/intel/igb/igb_main.c
drivers/net/ethernet/intel/igbvf/netdev.c
drivers/net/ethernet/intel/ixgbe/ixgbe.h
drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c

index 4c500a76972e9bc05fc2ed0a9a67a96d3d94b433..559443015cc5d7dddf238a2b21a30df968b72e93 100644 (file)
@@ -72,6 +72,8 @@ struct igb_adapter;
 #define IGB_MAX_VF_MC_ENTRIES              30
 #define IGB_MAX_VF_FUNCTIONS               8
 #define IGB_MAX_VFTA_ENTRIES               128
+#define IGB_82576_VF_DEV_ID                0x10CA
+#define IGB_I350_VF_DEV_ID                 0x1520
 
 struct vf_data_storage {
        unsigned char vf_mac_addresses[ETH_ALEN];
@@ -83,6 +85,7 @@ struct vf_data_storage {
        u16 pf_vlan; /* When set, guest VLAN config not allowed. */
        u16 pf_qos;
        u16 tx_rate;
+       struct pci_dev *vfdev;
 };
 
 #define IGB_VF_FLAG_CTS            0x00000001 /* VF is clear to send data */
index c10cc716fdece80ac48691045c335395216caaf3..837adbbce7722f36b85025b7d939130a703263c2 100644 (file)
@@ -162,6 +162,9 @@ static int igb_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate);
 static int igb_ndo_get_vf_config(struct net_device *netdev, int vf,
                                 struct ifla_vf_info *ivi);
 static void igb_check_vf_rate_limit(struct igb_adapter *);
+static int igb_vf_configure(struct igb_adapter *adapter, int vf);
+static int igb_find_enabled_vfs(struct igb_adapter *adapter);
+static int igb_check_vf_assignment(struct igb_adapter *adapter);
 
 #ifdef CONFIG_PM
 static int igb_suspend(struct pci_dev *, pm_message_t);
@@ -2232,8 +2235,12 @@ static void __devexit igb_remove(struct pci_dev *pdev)
        /* reclaim resources allocated to VFs */
        if (adapter->vf_data) {
                /* disable iov and allow time for transactions to clear */
-               pci_disable_sriov(pdev);
-               msleep(500);
+               if (!igb_check_vf_assignment(adapter)) {
+                       pci_disable_sriov(pdev);
+                       msleep(500);
+               } else {
+                       dev_info(&pdev->dev, "VF(s) assigned to guests!\n");
+               }
 
                kfree(adapter->vf_data);
                adapter->vf_data = NULL;
@@ -2270,42 +2277,49 @@ static void __devinit igb_probe_vfs(struct igb_adapter * adapter)
 {
 #ifdef CONFIG_PCI_IOV
        struct pci_dev *pdev = adapter->pdev;
+       int old_vfs = igb_find_enabled_vfs(adapter);
+       int i;
 
-       if (adapter->vfs_allocated_count) {
-               adapter->vf_data = kcalloc(adapter->vfs_allocated_count,
-                                          sizeof(struct vf_data_storage),
-                                          GFP_KERNEL);
-               /* if allocation failed then we do not support SR-IOV */
-               if (!adapter->vf_data) {
-                       adapter->vfs_allocated_count = 0;
-                       dev_err(&pdev->dev, "Unable to allocate memory for VF "
-                               "Data Storage\n");
-               }
+       if (old_vfs) {
+               dev_info(&pdev->dev, "%d pre-allocated VFs found - override "
+                        "max_vfs setting of %d\n", old_vfs, max_vfs);
+               adapter->vfs_allocated_count = old_vfs;
        }
 
-       if (pci_enable_sriov(pdev, adapter->vfs_allocated_count)) {
-               kfree(adapter->vf_data);
-               adapter->vf_data = NULL;
-#endif /* CONFIG_PCI_IOV */
+       if (!adapter->vfs_allocated_count)
+               return;
+
+       adapter->vf_data = kcalloc(adapter->vfs_allocated_count,
+                               sizeof(struct vf_data_storage), GFP_KERNEL);
+       /* if allocation failed then we do not support SR-IOV */
+       if (!adapter->vf_data) {
                adapter->vfs_allocated_count = 0;
-#ifdef CONFIG_PCI_IOV
-       } else {
-               unsigned char mac_addr[ETH_ALEN];
-               int i;
-               dev_info(&pdev->dev, "%d vfs allocated\n",
-                        adapter->vfs_allocated_count);
-               for (i = 0; i < adapter->vfs_allocated_count; i++) {
-                       random_ether_addr(mac_addr);
-                       igb_set_vf_mac(adapter, i, mac_addr);
-               }
-               /* DMA Coalescing is not supported in IOV mode. */
-               if (adapter->flags & IGB_FLAG_DMAC)
-                       adapter->flags &= ~IGB_FLAG_DMAC;
+               dev_err(&pdev->dev, "Unable to allocate memory for VF "
+                       "Data Storage\n");
+               goto out;
        }
+
+       if (!old_vfs) {
+               if (pci_enable_sriov(pdev, adapter->vfs_allocated_count))
+                       goto err_out;
+       }
+       dev_info(&pdev->dev, "%d VFs allocated\n",
+                adapter->vfs_allocated_count);
+       for (i = 0; i < adapter->vfs_allocated_count; i++)
+               igb_vf_configure(adapter, i);
+
+       /* DMA Coalescing is not supported in IOV mode. */
+       adapter->flags &= ~IGB_FLAG_DMAC;
+       goto out;
+err_out:
+       kfree(adapter->vf_data);
+       adapter->vf_data = NULL;
+       adapter->vfs_allocated_count = 0;
+out:
+       return;
 #endif /* CONFIG_PCI_IOV */
 }
 
-
 /**
  * igb_init_hw_timer - Initialize hardware timer used with IEEE 1588 timestamp
  * @adapter: board private structure to initialize
@@ -4917,6 +4931,109 @@ static int igb_notify_dca(struct notifier_block *nb, unsigned long event,
 }
 #endif /* CONFIG_IGB_DCA */
 
+#ifdef CONFIG_PCI_IOV
+static int igb_vf_configure(struct igb_adapter *adapter, int vf)
+{
+       unsigned char mac_addr[ETH_ALEN];
+       struct pci_dev *pdev = adapter->pdev;
+       struct e1000_hw *hw = &adapter->hw;
+       struct pci_dev *pvfdev;
+       unsigned int device_id;
+       u16 thisvf_devfn;
+
+       random_ether_addr(mac_addr);
+       igb_set_vf_mac(adapter, vf, mac_addr);
+
+       switch (adapter->hw.mac.type) {
+       case e1000_82576:
+               device_id = IGB_82576_VF_DEV_ID;
+               /* VF Stride for 82576 is 2 */
+               thisvf_devfn = (pdev->devfn + 0x80 + (vf << 1)) |
+                       (pdev->devfn & 1);
+               break;
+       case e1000_i350:
+               device_id = IGB_I350_VF_DEV_ID;
+               /* VF Stride for I350 is 4 */
+               thisvf_devfn = (pdev->devfn + 0x80 + (vf << 2)) |
+                               (pdev->devfn & 3);
+               break;
+       default:
+               device_id = 0;
+               thisvf_devfn = 0;
+               break;
+       }
+
+       pvfdev = pci_get_device(hw->vendor_id, device_id, NULL);
+       while (pvfdev) {
+               if (pvfdev->devfn == thisvf_devfn)
+                       break;
+               pvfdev = pci_get_device(hw->vendor_id,
+                                       device_id, pvfdev);
+       }
+
+       if (pvfdev)
+               adapter->vf_data[vf].vfdev = pvfdev;
+       else
+               dev_err(&pdev->dev,
+                       "Couldn't find pci dev ptr for VF %4.4x\n",
+                       thisvf_devfn);
+       return pvfdev != NULL;
+}
+
+static int igb_find_enabled_vfs(struct igb_adapter *adapter)
+{
+       struct e1000_hw *hw = &adapter->hw;
+       struct pci_dev *pdev = adapter->pdev;
+       struct pci_dev *pvfdev;
+       u16 vf_devfn = 0;
+       u16 vf_stride;
+       unsigned int device_id;
+       int vfs_found = 0;
+
+       switch (adapter->hw.mac.type) {
+       case e1000_82576:
+               device_id = IGB_82576_VF_DEV_ID;
+               /* VF Stride for 82576 is 2 */
+               vf_stride = 2;
+               break;
+       case e1000_i350:
+               device_id = IGB_I350_VF_DEV_ID;
+               /* VF Stride for I350 is 4 */
+               vf_stride = 4;
+               break;
+       default:
+               device_id = 0;
+               vf_stride = 0;
+               break;
+       }
+
+       vf_devfn = pdev->devfn + 0x80;
+       pvfdev = pci_get_device(hw->vendor_id, device_id, NULL);
+       while (pvfdev) {
+               if (pvfdev->devfn == vf_devfn)
+                       vfs_found++;
+               vf_devfn += vf_stride;
+               pvfdev = pci_get_device(hw->vendor_id,
+                                       device_id, pvfdev);
+       }
+
+       return vfs_found;
+}
+
+static int igb_check_vf_assignment(struct igb_adapter *adapter)
+{
+       int i;
+       for (i = 0; i < adapter->vfs_allocated_count; i++) {
+               if (adapter->vf_data[i].vfdev) {
+                       if (adapter->vf_data[i].vfdev->dev_flags &
+                           PCI_DEV_FLAGS_ASSIGNED)
+                               return true;
+               }
+       }
+       return false;
+}
+
+#endif
 static void igb_ping_all_vfs(struct igb_adapter *adapter)
 {
        struct e1000_hw *hw = &adapter->hw;
index 32b3044fa45cdf5d9d7cda6de26c6f4afda2ed83..23cc40f22d6fcbae27893acb6d09d716f6635cab 100644 (file)
@@ -102,8 +102,8 @@ static void igbvf_receive_skb(struct igbvf_adapter *adapter,
 {
        if (status & E1000_RXD_STAT_VP) {
                u16 vid = le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK;
-
-               __vlan_hwaccel_put_tag(skb, vid);
+               if (test_bit(vid, adapter->active_vlans))
+                       __vlan_hwaccel_put_tag(skb, vid);
        }
        netif_receive_skb(skb);
 }
index 6c4d693be08d42078ab31790324aff679c9c99d9..a8368d5cf6866aa061bc21a180f86d45894e86f3 100644 (file)
@@ -497,7 +497,8 @@ struct ixgbe_adapter {
        u64 rsc_total_count;
        u64 rsc_total_flush;
        u32 wol;
-       u16 eeprom_version;
+       u16 eeprom_verh;
+       u16 eeprom_verl;
        u16 eeprom_cap;
 
        int node;
index e02e911057de93e2ce9abcc1e68561b12021f685..ef2afefb0cd49dc13e9dcafd3abde34d8e795d4a 100644 (file)
@@ -1305,6 +1305,8 @@ static struct ixgbe_mac_operations mac_ops_82598 = {
 static struct ixgbe_eeprom_operations eeprom_ops_82598 = {
        .init_params            = &ixgbe_init_eeprom_params_generic,
        .read                   = &ixgbe_read_eerd_generic,
+       .write                  = &ixgbe_write_eeprom_generic,
+       .write_buffer           = &ixgbe_write_eeprom_buffer_bit_bang_generic,
        .read_buffer            = &ixgbe_read_eerd_buffer_generic,
        .calc_checksum          = &ixgbe_calc_eeprom_checksum_generic,
        .validate_checksum      = &ixgbe_validate_eeprom_checksum_generic,
index 35fa444556b3714424769d30a51b7c9e21ac6174..834f044be4c3d7fe15febecca9fcd8d8d44c0a59 100644 (file)
@@ -3341,7 +3341,7 @@ static u8 ixgbe_calculate_checksum(u8 *buffer, u32 length)
  *  Communicates with the manageability block.  On success return 0
  *  else return IXGBE_ERR_HOST_INTERFACE_COMMAND.
  **/
-static s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u8 *buffer,
+static s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer,
                                        u32 length)
 {
        u32 hicr, i;
@@ -3374,7 +3374,7 @@ static s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u8 *buffer,
         */
        for (i = 0; i < dword_len; i++)
                IXGBE_WRITE_REG_ARRAY(hw, IXGBE_FLEX_MNG,
-                                     i, *((u32 *)buffer + i));
+                                     i, cpu_to_le32(buffer[i]));
 
        /* Setting this bit tells the ARC that a new command is pending. */
        IXGBE_WRITE_REG(hw, IXGBE_HICR, hicr | IXGBE_HICR_C);
@@ -3398,9 +3398,10 @@ static s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u8 *buffer,
        dword_len = hdr_size >> 2;
 
        /* first pull in the header so we know the buffer length */
-       for (i = 0; i < dword_len; i++)
-               *((u32 *)buffer + i) =
-                       IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, i);
+       for (i = 0; i < dword_len; i++) {
+               buffer[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, i);
+               le32_to_cpus(&buffer[i]);
+       }
 
        /* If there is any thing in data position pull it in */
        buf_len = ((struct ixgbe_hic_hdr *)buffer)->buf_len;
@@ -3418,8 +3419,7 @@ static s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u8 *buffer,
 
        /* Pull in the rest of the buffer (i is where we left off)*/
        for (; i < buf_len; i++)
-               *((u32 *)buffer + i) =
-                       IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, i);
+               buffer[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, i);
 
 out:
        return ret_val;
@@ -3465,7 +3465,7 @@ s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min,
        fw_cmd.pad2 = 0;
 
        for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
-               ret_val = ixgbe_host_interface_command(hw, (u8 *)&fw_cmd,
+               ret_val = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd,
                                                       sizeof(fw_cmd));
                if (ret_val != 0)
                        continue;
index e102ff6fb08d3f0c5998bb688e06ca0d7d76b215..70d58c3849b0592fa767319a0f14c5551330f15a 100644 (file)
@@ -814,26 +814,97 @@ static int ixgbe_get_eeprom(struct net_device *netdev,
        return ret_val;
 }
 
+static int ixgbe_set_eeprom(struct net_device *netdev,
+                           struct ethtool_eeprom *eeprom, u8 *bytes)
+{
+       struct ixgbe_adapter *adapter = netdev_priv(netdev);
+       struct ixgbe_hw *hw = &adapter->hw;
+       u16 *eeprom_buff;
+       void *ptr;
+       int max_len, first_word, last_word, ret_val = 0;
+       u16 i;
+
+       if (eeprom->len == 0)
+               return -EINVAL;
+
+       if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
+               return -EINVAL;
+
+       max_len = hw->eeprom.word_size * 2;
+
+       first_word = eeprom->offset >> 1;
+       last_word = (eeprom->offset + eeprom->len - 1) >> 1;
+       eeprom_buff = kmalloc(max_len, GFP_KERNEL);
+       if (!eeprom_buff)
+               return -ENOMEM;
+
+       ptr = eeprom_buff;
+
+       if (eeprom->offset & 1) {
+               /*
+                * need read/modify/write of first changed EEPROM word
+                * only the second byte of the word is being modified
+                */
+               ret_val = hw->eeprom.ops.read(hw, first_word, &eeprom_buff[0]);
+               if (ret_val)
+                       goto err;
+
+               ptr++;
+       }
+       if ((eeprom->offset + eeprom->len) & 1) {
+               /*
+                * need read/modify/write of last changed EEPROM word
+                * only the first byte of the word is being modified
+                */
+               ret_val = hw->eeprom.ops.read(hw, last_word,
+                                         &eeprom_buff[last_word - first_word]);
+               if (ret_val)
+                       goto err;
+       }
+
+       /* Device's eeprom is always little-endian, word addressable */
+       for (i = 0; i < last_word - first_word + 1; i++)
+               le16_to_cpus(&eeprom_buff[i]);
+
+       memcpy(ptr, bytes, eeprom->len);
+
+       for (i = 0; i < last_word - first_word + 1; i++)
+               cpu_to_le16s(&eeprom_buff[i]);
+
+       ret_val = hw->eeprom.ops.write_buffer(hw, first_word,
+                                             last_word - first_word + 1,
+                                             eeprom_buff);
+
+       /* Update the checksum */
+       if (ret_val == 0)
+               hw->eeprom.ops.update_checksum(hw);
+
+err:
+       kfree(eeprom_buff);
+       return ret_val;
+}
+
 static void ixgbe_get_drvinfo(struct net_device *netdev,
                               struct ethtool_drvinfo *drvinfo)
 {
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
        char firmware_version[32];
+       u32 nvm_track_id;
 
        strncpy(drvinfo->driver, ixgbe_driver_name,
                sizeof(drvinfo->driver) - 1);
        strncpy(drvinfo->version, ixgbe_driver_version,
                sizeof(drvinfo->version) - 1);
 
-       snprintf(firmware_version, sizeof(firmware_version), "%d.%d-%d",
-                (adapter->eeprom_version & 0xF000) >> 12,
-                (adapter->eeprom_version & 0x0FF0) >> 4,
-                adapter->eeprom_version & 0x000F);
+       nvm_track_id = (adapter->eeprom_verh << 16) |
+                       adapter->eeprom_verl;
+       snprintf(firmware_version, sizeof(firmware_version), "0x%08x",
+                nvm_track_id);
 
        strncpy(drvinfo->fw_version, firmware_version,
-               sizeof(drvinfo->fw_version));
+               sizeof(drvinfo->fw_version) - 1);
        strncpy(drvinfo->bus_info, pci_name(adapter->pdev),
-               sizeof(drvinfo->bus_info));
+               sizeof(drvinfo->bus_info) - 1);
        drvinfo->n_stats = IXGBE_STATS_LEN;
        drvinfo->testinfo_len = IXGBE_TEST_LEN;
        drvinfo->regdump_len = ixgbe_get_regs_len(netdev);
@@ -2524,6 +2595,7 @@ static const struct ethtool_ops ixgbe_ethtool_ops = {
        .get_link               = ethtool_op_get_link,
        .get_eeprom_len         = ixgbe_get_eeprom_len,
        .get_eeprom             = ixgbe_get_eeprom,
+       .set_eeprom             = ixgbe_set_eeprom,
        .get_ringparam          = ixgbe_get_ringparam,
        .set_ringparam          = ixgbe_set_ringparam,
        .get_pauseparam         = ixgbe_get_pauseparam,
index fb7d8842a36267f4c7f3dd377eee7c1f11f83351..8075d11b4cdeeb81d68148981133a0c3bb50d5ce 100644 (file)
@@ -7640,6 +7640,10 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
        }
        device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
 
+       /* save off EEPROM version number */
+       hw->eeprom.ops.read(hw, 0x2e, &adapter->eeprom_verh);
+       hw->eeprom.ops.read(hw, 0x2d, &adapter->eeprom_verl);
+
        /* pick up the PCI bus settings for reporting later */
        hw->mac.ops.get_bus_info(hw);
 
@@ -7672,9 +7676,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
                           "is required.\n");
        }
 
-       /* save off EEPROM version number */
-       hw->eeprom.ops.read(hw, 0x29, &adapter->eeprom_version);
-
        /* reset the hardware with the new settings */
        err = hw->mac.ops.start_hw(hw);