diff options
author | David S. Miller <davem@davemloft.net> | 2011-10-17 20:21:50 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-10-17 20:21:50 -0400 |
commit | f7ba35da583cf6aefba887a8dcf86acec4f3a350 (patch) | |
tree | e5355b5c725b5c57e014f4e6b580cf018f6bc3de /drivers | |
parent | 01b7806cdce3d3cf1626a1e79389f30512703069 (diff) | |
parent | 15e5209f1c606e7c3e9b268f5c7b70b414a859cb (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-next
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/ethernet/intel/igb/igb.h | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igb/igb_main.c | 177 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igbvf/netdev.c | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe.h | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_common.c | 16 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 84 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 7 |
8 files changed, 246 insertions, 50 deletions
diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h index 4c500a76972e..559443015cc5 100644 --- a/drivers/net/ethernet/intel/igb/igb.h +++ b/drivers/net/ethernet/intel/igb/igb.h | |||
@@ -72,6 +72,8 @@ struct igb_adapter; | |||
72 | #define IGB_MAX_VF_MC_ENTRIES 30 | 72 | #define IGB_MAX_VF_MC_ENTRIES 30 |
73 | #define IGB_MAX_VF_FUNCTIONS 8 | 73 | #define IGB_MAX_VF_FUNCTIONS 8 |
74 | #define IGB_MAX_VFTA_ENTRIES 128 | 74 | #define IGB_MAX_VFTA_ENTRIES 128 |
75 | #define IGB_82576_VF_DEV_ID 0x10CA | ||
76 | #define IGB_I350_VF_DEV_ID 0x1520 | ||
75 | 77 | ||
76 | struct vf_data_storage { | 78 | struct vf_data_storage { |
77 | unsigned char vf_mac_addresses[ETH_ALEN]; | 79 | unsigned char vf_mac_addresses[ETH_ALEN]; |
@@ -83,6 +85,7 @@ struct vf_data_storage { | |||
83 | u16 pf_vlan; /* When set, guest VLAN config not allowed. */ | 85 | u16 pf_vlan; /* When set, guest VLAN config not allowed. */ |
84 | u16 pf_qos; | 86 | u16 pf_qos; |
85 | u16 tx_rate; | 87 | u16 tx_rate; |
88 | struct pci_dev *vfdev; | ||
86 | }; | 89 | }; |
87 | 90 | ||
88 | #define IGB_VF_FLAG_CTS 0x00000001 /* VF is clear to send data */ | 91 | #define IGB_VF_FLAG_CTS 0x00000001 /* VF is clear to send data */ |
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index c10cc716fdec..837adbbce772 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c | |||
@@ -162,6 +162,9 @@ static int igb_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate); | |||
162 | static int igb_ndo_get_vf_config(struct net_device *netdev, int vf, | 162 | static int igb_ndo_get_vf_config(struct net_device *netdev, int vf, |
163 | struct ifla_vf_info *ivi); | 163 | struct ifla_vf_info *ivi); |
164 | static void igb_check_vf_rate_limit(struct igb_adapter *); | 164 | static void igb_check_vf_rate_limit(struct igb_adapter *); |
165 | static int igb_vf_configure(struct igb_adapter *adapter, int vf); | ||
166 | static int igb_find_enabled_vfs(struct igb_adapter *adapter); | ||
167 | static int igb_check_vf_assignment(struct igb_adapter *adapter); | ||
165 | 168 | ||
166 | #ifdef CONFIG_PM | 169 | #ifdef CONFIG_PM |
167 | static int igb_suspend(struct pci_dev *, pm_message_t); | 170 | static int igb_suspend(struct pci_dev *, pm_message_t); |
@@ -2232,8 +2235,12 @@ static void __devexit igb_remove(struct pci_dev *pdev) | |||
2232 | /* reclaim resources allocated to VFs */ | 2235 | /* reclaim resources allocated to VFs */ |
2233 | if (adapter->vf_data) { | 2236 | if (adapter->vf_data) { |
2234 | /* disable iov and allow time for transactions to clear */ | 2237 | /* disable iov and allow time for transactions to clear */ |
2235 | pci_disable_sriov(pdev); | 2238 | if (!igb_check_vf_assignment(adapter)) { |
2236 | msleep(500); | 2239 | pci_disable_sriov(pdev); |
2240 | msleep(500); | ||
2241 | } else { | ||
2242 | dev_info(&pdev->dev, "VF(s) assigned to guests!\n"); | ||
2243 | } | ||
2237 | 2244 | ||
2238 | kfree(adapter->vf_data); | 2245 | kfree(adapter->vf_data); |
2239 | adapter->vf_data = NULL; | 2246 | adapter->vf_data = NULL; |
@@ -2270,42 +2277,49 @@ static void __devinit igb_probe_vfs(struct igb_adapter * adapter) | |||
2270 | { | 2277 | { |
2271 | #ifdef CONFIG_PCI_IOV | 2278 | #ifdef CONFIG_PCI_IOV |
2272 | struct pci_dev *pdev = adapter->pdev; | 2279 | struct pci_dev *pdev = adapter->pdev; |
2280 | int old_vfs = igb_find_enabled_vfs(adapter); | ||
2281 | int i; | ||
2273 | 2282 | ||
2274 | if (adapter->vfs_allocated_count) { | 2283 | if (old_vfs) { |
2275 | adapter->vf_data = kcalloc(adapter->vfs_allocated_count, | 2284 | dev_info(&pdev->dev, "%d pre-allocated VFs found - override " |
2276 | sizeof(struct vf_data_storage), | 2285 | "max_vfs setting of %d\n", old_vfs, max_vfs); |
2277 | GFP_KERNEL); | 2286 | adapter->vfs_allocated_count = old_vfs; |
2278 | /* if allocation failed then we do not support SR-IOV */ | ||
2279 | if (!adapter->vf_data) { | ||
2280 | adapter->vfs_allocated_count = 0; | ||
2281 | dev_err(&pdev->dev, "Unable to allocate memory for VF " | ||
2282 | "Data Storage\n"); | ||
2283 | } | ||
2284 | } | 2287 | } |
2285 | 2288 | ||
2286 | if (pci_enable_sriov(pdev, adapter->vfs_allocated_count)) { | 2289 | if (!adapter->vfs_allocated_count) |
2287 | kfree(adapter->vf_data); | 2290 | return; |
2288 | adapter->vf_data = NULL; | 2291 | |
2289 | #endif /* CONFIG_PCI_IOV */ | 2292 | adapter->vf_data = kcalloc(adapter->vfs_allocated_count, |
2293 | sizeof(struct vf_data_storage), GFP_KERNEL); | ||
2294 | /* if allocation failed then we do not support SR-IOV */ | ||
2295 | if (!adapter->vf_data) { | ||
2290 | adapter->vfs_allocated_count = 0; | 2296 | adapter->vfs_allocated_count = 0; |
2291 | #ifdef CONFIG_PCI_IOV | 2297 | dev_err(&pdev->dev, "Unable to allocate memory for VF " |
2292 | } else { | 2298 | "Data Storage\n"); |
2293 | unsigned char mac_addr[ETH_ALEN]; | 2299 | goto out; |
2294 | int i; | ||
2295 | dev_info(&pdev->dev, "%d vfs allocated\n", | ||
2296 | adapter->vfs_allocated_count); | ||
2297 | for (i = 0; i < adapter->vfs_allocated_count; i++) { | ||
2298 | random_ether_addr(mac_addr); | ||
2299 | igb_set_vf_mac(adapter, i, mac_addr); | ||
2300 | } | ||
2301 | /* DMA Coalescing is not supported in IOV mode. */ | ||
2302 | if (adapter->flags & IGB_FLAG_DMAC) | ||
2303 | adapter->flags &= ~IGB_FLAG_DMAC; | ||
2304 | } | 2300 | } |
2301 | |||
2302 | if (!old_vfs) { | ||
2303 | if (pci_enable_sriov(pdev, adapter->vfs_allocated_count)) | ||
2304 | goto err_out; | ||
2305 | } | ||
2306 | dev_info(&pdev->dev, "%d VFs allocated\n", | ||
2307 | adapter->vfs_allocated_count); | ||
2308 | for (i = 0; i < adapter->vfs_allocated_count; i++) | ||
2309 | igb_vf_configure(adapter, i); | ||
2310 | |||
2311 | /* DMA Coalescing is not supported in IOV mode. */ | ||
2312 | adapter->flags &= ~IGB_FLAG_DMAC; | ||
2313 | goto out; | ||
2314 | err_out: | ||
2315 | kfree(adapter->vf_data); | ||
2316 | adapter->vf_data = NULL; | ||
2317 | adapter->vfs_allocated_count = 0; | ||
2318 | out: | ||
2319 | return; | ||
2305 | #endif /* CONFIG_PCI_IOV */ | 2320 | #endif /* CONFIG_PCI_IOV */ |
2306 | } | 2321 | } |
2307 | 2322 | ||
2308 | |||
2309 | /** | 2323 | /** |
2310 | * igb_init_hw_timer - Initialize hardware timer used with IEEE 1588 timestamp | 2324 | * igb_init_hw_timer - Initialize hardware timer used with IEEE 1588 timestamp |
2311 | * @adapter: board private structure to initialize | 2325 | * @adapter: board private structure to initialize |
@@ -4917,6 +4931,109 @@ static int igb_notify_dca(struct notifier_block *nb, unsigned long event, | |||
4917 | } | 4931 | } |
4918 | #endif /* CONFIG_IGB_DCA */ | 4932 | #endif /* CONFIG_IGB_DCA */ |
4919 | 4933 | ||
4934 | #ifdef CONFIG_PCI_IOV | ||
4935 | static int igb_vf_configure(struct igb_adapter *adapter, int vf) | ||
4936 | { | ||
4937 | unsigned char mac_addr[ETH_ALEN]; | ||
4938 | struct pci_dev *pdev = adapter->pdev; | ||
4939 | struct e1000_hw *hw = &adapter->hw; | ||
4940 | struct pci_dev *pvfdev; | ||
4941 | unsigned int device_id; | ||
4942 | u16 thisvf_devfn; | ||
4943 | |||
4944 | random_ether_addr(mac_addr); | ||
4945 | igb_set_vf_mac(adapter, vf, mac_addr); | ||
4946 | |||
4947 | switch (adapter->hw.mac.type) { | ||
4948 | case e1000_82576: | ||
4949 | device_id = IGB_82576_VF_DEV_ID; | ||
4950 | /* VF Stride for 82576 is 2 */ | ||
4951 | thisvf_devfn = (pdev->devfn + 0x80 + (vf << 1)) | | ||
4952 | (pdev->devfn & 1); | ||
4953 | break; | ||
4954 | case e1000_i350: | ||
4955 | device_id = IGB_I350_VF_DEV_ID; | ||
4956 | /* VF Stride for I350 is 4 */ | ||
4957 | thisvf_devfn = (pdev->devfn + 0x80 + (vf << 2)) | | ||
4958 | (pdev->devfn & 3); | ||
4959 | break; | ||
4960 | default: | ||
4961 | device_id = 0; | ||
4962 | thisvf_devfn = 0; | ||
4963 | break; | ||
4964 | } | ||
4965 | |||
4966 | pvfdev = pci_get_device(hw->vendor_id, device_id, NULL); | ||
4967 | while (pvfdev) { | ||
4968 | if (pvfdev->devfn == thisvf_devfn) | ||
4969 | break; | ||
4970 | pvfdev = pci_get_device(hw->vendor_id, | ||
4971 | device_id, pvfdev); | ||
4972 | } | ||
4973 | |||
4974 | if (pvfdev) | ||
4975 | adapter->vf_data[vf].vfdev = pvfdev; | ||
4976 | else | ||
4977 | dev_err(&pdev->dev, | ||
4978 | "Couldn't find pci dev ptr for VF %4.4x\n", | ||
4979 | thisvf_devfn); | ||
4980 | return pvfdev != NULL; | ||
4981 | } | ||
4982 | |||
4983 | static int igb_find_enabled_vfs(struct igb_adapter *adapter) | ||
4984 | { | ||
4985 | struct e1000_hw *hw = &adapter->hw; | ||
4986 | struct pci_dev *pdev = adapter->pdev; | ||
4987 | struct pci_dev *pvfdev; | ||
4988 | u16 vf_devfn = 0; | ||
4989 | u16 vf_stride; | ||
4990 | unsigned int device_id; | ||
4991 | int vfs_found = 0; | ||
4992 | |||
4993 | switch (adapter->hw.mac.type) { | ||
4994 | case e1000_82576: | ||
4995 | device_id = IGB_82576_VF_DEV_ID; | ||
4996 | /* VF Stride for 82576 is 2 */ | ||
4997 | vf_stride = 2; | ||
4998 | break; | ||
4999 | case e1000_i350: | ||
5000 | device_id = IGB_I350_VF_DEV_ID; | ||
5001 | /* VF Stride for I350 is 4 */ | ||
5002 | vf_stride = 4; | ||
5003 | break; | ||
5004 | default: | ||
5005 | device_id = 0; | ||
5006 | vf_stride = 0; | ||
5007 | break; | ||
5008 | } | ||
5009 | |||
5010 | vf_devfn = pdev->devfn + 0x80; | ||
5011 | pvfdev = pci_get_device(hw->vendor_id, device_id, NULL); | ||
5012 | while (pvfdev) { | ||
5013 | if (pvfdev->devfn == vf_devfn) | ||
5014 | vfs_found++; | ||
5015 | vf_devfn += vf_stride; | ||
5016 | pvfdev = pci_get_device(hw->vendor_id, | ||
5017 | device_id, pvfdev); | ||
5018 | } | ||
5019 | |||
5020 | return vfs_found; | ||
5021 | } | ||
5022 | |||
5023 | static int igb_check_vf_assignment(struct igb_adapter *adapter) | ||
5024 | { | ||
5025 | int i; | ||
5026 | for (i = 0; i < adapter->vfs_allocated_count; i++) { | ||
5027 | if (adapter->vf_data[i].vfdev) { | ||
5028 | if (adapter->vf_data[i].vfdev->dev_flags & | ||
5029 | PCI_DEV_FLAGS_ASSIGNED) | ||
5030 | return true; | ||
5031 | } | ||
5032 | } | ||
5033 | return false; | ||
5034 | } | ||
5035 | |||
5036 | #endif | ||
4920 | static void igb_ping_all_vfs(struct igb_adapter *adapter) | 5037 | static void igb_ping_all_vfs(struct igb_adapter *adapter) |
4921 | { | 5038 | { |
4922 | struct e1000_hw *hw = &adapter->hw; | 5039 | struct e1000_hw *hw = &adapter->hw; |
diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c index 32b3044fa45c..23cc40f22d6f 100644 --- a/drivers/net/ethernet/intel/igbvf/netdev.c +++ b/drivers/net/ethernet/intel/igbvf/netdev.c | |||
@@ -102,8 +102,8 @@ static void igbvf_receive_skb(struct igbvf_adapter *adapter, | |||
102 | { | 102 | { |
103 | if (status & E1000_RXD_STAT_VP) { | 103 | if (status & E1000_RXD_STAT_VP) { |
104 | u16 vid = le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK; | 104 | u16 vid = le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK; |
105 | 105 | if (test_bit(vid, adapter->active_vlans)) | |
106 | __vlan_hwaccel_put_tag(skb, vid); | 106 | __vlan_hwaccel_put_tag(skb, vid); |
107 | } | 107 | } |
108 | netif_receive_skb(skb); | 108 | netif_receive_skb(skb); |
109 | } | 109 | } |
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index 6c4d693be08d..a8368d5cf686 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h | |||
@@ -497,7 +497,8 @@ struct ixgbe_adapter { | |||
497 | u64 rsc_total_count; | 497 | u64 rsc_total_count; |
498 | u64 rsc_total_flush; | 498 | u64 rsc_total_flush; |
499 | u32 wol; | 499 | u32 wol; |
500 | u16 eeprom_version; | 500 | u16 eeprom_verh; |
501 | u16 eeprom_verl; | ||
501 | u16 eeprom_cap; | 502 | u16 eeprom_cap; |
502 | 503 | ||
503 | int node; | 504 | int node; |
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c index e02e911057de..ef2afefb0cd4 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c | |||
@@ -1305,6 +1305,8 @@ static struct ixgbe_mac_operations mac_ops_82598 = { | |||
1305 | static struct ixgbe_eeprom_operations eeprom_ops_82598 = { | 1305 | static struct ixgbe_eeprom_operations eeprom_ops_82598 = { |
1306 | .init_params = &ixgbe_init_eeprom_params_generic, | 1306 | .init_params = &ixgbe_init_eeprom_params_generic, |
1307 | .read = &ixgbe_read_eerd_generic, | 1307 | .read = &ixgbe_read_eerd_generic, |
1308 | .write = &ixgbe_write_eeprom_generic, | ||
1309 | .write_buffer = &ixgbe_write_eeprom_buffer_bit_bang_generic, | ||
1308 | .read_buffer = &ixgbe_read_eerd_buffer_generic, | 1310 | .read_buffer = &ixgbe_read_eerd_buffer_generic, |
1309 | .calc_checksum = &ixgbe_calc_eeprom_checksum_generic, | 1311 | .calc_checksum = &ixgbe_calc_eeprom_checksum_generic, |
1310 | .validate_checksum = &ixgbe_validate_eeprom_checksum_generic, | 1312 | .validate_checksum = &ixgbe_validate_eeprom_checksum_generic, |
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index 35fa444556b3..834f044be4c3 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c | |||
@@ -3341,7 +3341,7 @@ static u8 ixgbe_calculate_checksum(u8 *buffer, u32 length) | |||
3341 | * Communicates with the manageability block. On success return 0 | 3341 | * Communicates with the manageability block. On success return 0 |
3342 | * else return IXGBE_ERR_HOST_INTERFACE_COMMAND. | 3342 | * else return IXGBE_ERR_HOST_INTERFACE_COMMAND. |
3343 | **/ | 3343 | **/ |
3344 | static s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u8 *buffer, | 3344 | static s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer, |
3345 | u32 length) | 3345 | u32 length) |
3346 | { | 3346 | { |
3347 | u32 hicr, i; | 3347 | u32 hicr, i; |
@@ -3374,7 +3374,7 @@ static s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u8 *buffer, | |||
3374 | */ | 3374 | */ |
3375 | for (i = 0; i < dword_len; i++) | 3375 | for (i = 0; i < dword_len; i++) |
3376 | IXGBE_WRITE_REG_ARRAY(hw, IXGBE_FLEX_MNG, | 3376 | IXGBE_WRITE_REG_ARRAY(hw, IXGBE_FLEX_MNG, |
3377 | i, *((u32 *)buffer + i)); | 3377 | i, cpu_to_le32(buffer[i])); |
3378 | 3378 | ||
3379 | /* Setting this bit tells the ARC that a new command is pending. */ | 3379 | /* Setting this bit tells the ARC that a new command is pending. */ |
3380 | IXGBE_WRITE_REG(hw, IXGBE_HICR, hicr | IXGBE_HICR_C); | 3380 | 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, | |||
3398 | dword_len = hdr_size >> 2; | 3398 | dword_len = hdr_size >> 2; |
3399 | 3399 | ||
3400 | /* first pull in the header so we know the buffer length */ | 3400 | /* first pull in the header so we know the buffer length */ |
3401 | for (i = 0; i < dword_len; i++) | 3401 | for (i = 0; i < dword_len; i++) { |
3402 | *((u32 *)buffer + i) = | 3402 | buffer[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, i); |
3403 | IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, i); | 3403 | le32_to_cpus(&buffer[i]); |
3404 | } | ||
3404 | 3405 | ||
3405 | /* If there is any thing in data position pull it in */ | 3406 | /* If there is any thing in data position pull it in */ |
3406 | buf_len = ((struct ixgbe_hic_hdr *)buffer)->buf_len; | 3407 | 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, | |||
3418 | 3419 | ||
3419 | /* Pull in the rest of the buffer (i is where we left off)*/ | 3420 | /* Pull in the rest of the buffer (i is where we left off)*/ |
3420 | for (; i < buf_len; i++) | 3421 | for (; i < buf_len; i++) |
3421 | *((u32 *)buffer + i) = | 3422 | buffer[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, i); |
3422 | IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, i); | ||
3423 | 3423 | ||
3424 | out: | 3424 | out: |
3425 | return ret_val; | 3425 | return ret_val; |
@@ -3465,7 +3465,7 @@ s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min, | |||
3465 | fw_cmd.pad2 = 0; | 3465 | fw_cmd.pad2 = 0; |
3466 | 3466 | ||
3467 | for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) { | 3467 | for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) { |
3468 | ret_val = ixgbe_host_interface_command(hw, (u8 *)&fw_cmd, | 3468 | ret_val = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd, |
3469 | sizeof(fw_cmd)); | 3469 | sizeof(fw_cmd)); |
3470 | if (ret_val != 0) | 3470 | if (ret_val != 0) |
3471 | continue; | 3471 | continue; |
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c index e102ff6fb08d..70d58c3849b0 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c | |||
@@ -814,26 +814,97 @@ static int ixgbe_get_eeprom(struct net_device *netdev, | |||
814 | return ret_val; | 814 | return ret_val; |
815 | } | 815 | } |
816 | 816 | ||
817 | static int ixgbe_set_eeprom(struct net_device *netdev, | ||
818 | struct ethtool_eeprom *eeprom, u8 *bytes) | ||
819 | { | ||
820 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | ||
821 | struct ixgbe_hw *hw = &adapter->hw; | ||
822 | u16 *eeprom_buff; | ||
823 | void *ptr; | ||
824 | int max_len, first_word, last_word, ret_val = 0; | ||
825 | u16 i; | ||
826 | |||
827 | if (eeprom->len == 0) | ||
828 | return -EINVAL; | ||
829 | |||
830 | if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16))) | ||
831 | return -EINVAL; | ||
832 | |||
833 | max_len = hw->eeprom.word_size * 2; | ||
834 | |||
835 | first_word = eeprom->offset >> 1; | ||
836 | last_word = (eeprom->offset + eeprom->len - 1) >> 1; | ||
837 | eeprom_buff = kmalloc(max_len, GFP_KERNEL); | ||
838 | if (!eeprom_buff) | ||
839 | return -ENOMEM; | ||
840 | |||
841 | ptr = eeprom_buff; | ||
842 | |||
843 | if (eeprom->offset & 1) { | ||
844 | /* | ||
845 | * need read/modify/write of first changed EEPROM word | ||
846 | * only the second byte of the word is being modified | ||
847 | */ | ||
848 | ret_val = hw->eeprom.ops.read(hw, first_word, &eeprom_buff[0]); | ||
849 | if (ret_val) | ||
850 | goto err; | ||
851 | |||
852 | ptr++; | ||
853 | } | ||
854 | if ((eeprom->offset + eeprom->len) & 1) { | ||
855 | /* | ||
856 | * need read/modify/write of last changed EEPROM word | ||
857 | * only the first byte of the word is being modified | ||
858 | */ | ||
859 | ret_val = hw->eeprom.ops.read(hw, last_word, | ||
860 | &eeprom_buff[last_word - first_word]); | ||
861 | if (ret_val) | ||
862 | goto err; | ||
863 | } | ||
864 | |||
865 | /* Device's eeprom is always little-endian, word addressable */ | ||
866 | for (i = 0; i < last_word - first_word + 1; i++) | ||
867 | le16_to_cpus(&eeprom_buff[i]); | ||
868 | |||
869 | memcpy(ptr, bytes, eeprom->len); | ||
870 | |||
871 | for (i = 0; i < last_word - first_word + 1; i++) | ||
872 | cpu_to_le16s(&eeprom_buff[i]); | ||
873 | |||
874 | ret_val = hw->eeprom.ops.write_buffer(hw, first_word, | ||
875 | last_word - first_word + 1, | ||
876 | eeprom_buff); | ||
877 | |||
878 | /* Update the checksum */ | ||
879 | if (ret_val == 0) | ||
880 | hw->eeprom.ops.update_checksum(hw); | ||
881 | |||
882 | err: | ||
883 | kfree(eeprom_buff); | ||
884 | return ret_val; | ||
885 | } | ||
886 | |||
817 | static void ixgbe_get_drvinfo(struct net_device *netdev, | 887 | static void ixgbe_get_drvinfo(struct net_device *netdev, |
818 | struct ethtool_drvinfo *drvinfo) | 888 | struct ethtool_drvinfo *drvinfo) |
819 | { | 889 | { |
820 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 890 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
821 | char firmware_version[32]; | 891 | char firmware_version[32]; |
892 | u32 nvm_track_id; | ||
822 | 893 | ||
823 | strncpy(drvinfo->driver, ixgbe_driver_name, | 894 | strncpy(drvinfo->driver, ixgbe_driver_name, |
824 | sizeof(drvinfo->driver) - 1); | 895 | sizeof(drvinfo->driver) - 1); |
825 | strncpy(drvinfo->version, ixgbe_driver_version, | 896 | strncpy(drvinfo->version, ixgbe_driver_version, |
826 | sizeof(drvinfo->version) - 1); | 897 | sizeof(drvinfo->version) - 1); |
827 | 898 | ||
828 | snprintf(firmware_version, sizeof(firmware_version), "%d.%d-%d", | 899 | nvm_track_id = (adapter->eeprom_verh << 16) | |
829 | (adapter->eeprom_version & 0xF000) >> 12, | 900 | adapter->eeprom_verl; |
830 | (adapter->eeprom_version & 0x0FF0) >> 4, | 901 | snprintf(firmware_version, sizeof(firmware_version), "0x%08x", |
831 | adapter->eeprom_version & 0x000F); | 902 | nvm_track_id); |
832 | 903 | ||
833 | strncpy(drvinfo->fw_version, firmware_version, | 904 | strncpy(drvinfo->fw_version, firmware_version, |
834 | sizeof(drvinfo->fw_version)); | 905 | sizeof(drvinfo->fw_version) - 1); |
835 | strncpy(drvinfo->bus_info, pci_name(adapter->pdev), | 906 | strncpy(drvinfo->bus_info, pci_name(adapter->pdev), |
836 | sizeof(drvinfo->bus_info)); | 907 | sizeof(drvinfo->bus_info) - 1); |
837 | drvinfo->n_stats = IXGBE_STATS_LEN; | 908 | drvinfo->n_stats = IXGBE_STATS_LEN; |
838 | drvinfo->testinfo_len = IXGBE_TEST_LEN; | 909 | drvinfo->testinfo_len = IXGBE_TEST_LEN; |
839 | drvinfo->regdump_len = ixgbe_get_regs_len(netdev); | 910 | drvinfo->regdump_len = ixgbe_get_regs_len(netdev); |
@@ -2524,6 +2595,7 @@ static const struct ethtool_ops ixgbe_ethtool_ops = { | |||
2524 | .get_link = ethtool_op_get_link, | 2595 | .get_link = ethtool_op_get_link, |
2525 | .get_eeprom_len = ixgbe_get_eeprom_len, | 2596 | .get_eeprom_len = ixgbe_get_eeprom_len, |
2526 | .get_eeprom = ixgbe_get_eeprom, | 2597 | .get_eeprom = ixgbe_get_eeprom, |
2598 | .set_eeprom = ixgbe_set_eeprom, | ||
2527 | .get_ringparam = ixgbe_get_ringparam, | 2599 | .get_ringparam = ixgbe_get_ringparam, |
2528 | .set_ringparam = ixgbe_set_ringparam, | 2600 | .set_ringparam = ixgbe_set_ringparam, |
2529 | .get_pauseparam = ixgbe_get_pauseparam, | 2601 | .get_pauseparam = ixgbe_get_pauseparam, |
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index fb7d8842a362..8075d11b4cde 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | |||
@@ -7640,6 +7640,10 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, | |||
7640 | } | 7640 | } |
7641 | device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); | 7641 | device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); |
7642 | 7642 | ||
7643 | /* save off EEPROM version number */ | ||
7644 | hw->eeprom.ops.read(hw, 0x2e, &adapter->eeprom_verh); | ||
7645 | hw->eeprom.ops.read(hw, 0x2d, &adapter->eeprom_verl); | ||
7646 | |||
7643 | /* pick up the PCI bus settings for reporting later */ | 7647 | /* pick up the PCI bus settings for reporting later */ |
7644 | hw->mac.ops.get_bus_info(hw); | 7648 | hw->mac.ops.get_bus_info(hw); |
7645 | 7649 | ||
@@ -7672,9 +7676,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, | |||
7672 | "is required.\n"); | 7676 | "is required.\n"); |
7673 | } | 7677 | } |
7674 | 7678 | ||
7675 | /* save off EEPROM version number */ | ||
7676 | hw->eeprom.ops.read(hw, 0x29, &adapter->eeprom_version); | ||
7677 | |||
7678 | /* reset the hardware with the new settings */ | 7679 | /* reset the hardware with the new settings */ |
7679 | err = hw->mac.ops.start_hw(hw); | 7680 | err = hw->mac.ops.start_hw(hw); |
7680 | 7681 | ||