diff options
author | Shreyas Bhatewara <sbhatewara@vmware.com> | 2011-01-14 09:59:57 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-01-16 00:21:14 -0500 |
commit | 83d0feffc5695d7dc24c6b8dac9ab265533beb78 (patch) | |
tree | a1fc2e1e73827fb838657cdf75814c15b3efc746 /drivers/net/vmxnet3/vmxnet3_drv.c | |
parent | 51956cd68b0c3039968485317b77a89dfec95eab (diff) |
vmxnet3: Add locking for access to command register
Access to cmd register is racey, especially in smp environments. Protect
it using a spinlock.
Signed-off-by: Matthieu Bucchianeri <matthieu@vmware.com>
Signed-off-by: Shreyas N Bhatewara <sbhatewara@vmware.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/vmxnet3/vmxnet3_drv.c')
-rw-r--r-- | drivers/net/vmxnet3/vmxnet3_drv.c | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 20ef4f36ea2..3b5b1347757 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c | |||
@@ -142,9 +142,13 @@ vmxnet3_check_link(struct vmxnet3_adapter *adapter, bool affectTxQueue) | |||
142 | { | 142 | { |
143 | u32 ret; | 143 | u32 ret; |
144 | int i; | 144 | int i; |
145 | unsigned long flags; | ||
145 | 146 | ||
147 | spin_lock_irqsave(&adapter->cmd_lock, flags); | ||
146 | VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_CMD_GET_LINK); | 148 | VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_CMD_GET_LINK); |
147 | ret = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD); | 149 | ret = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD); |
150 | spin_unlock_irqrestore(&adapter->cmd_lock, flags); | ||
151 | |||
148 | adapter->link_speed = ret >> 16; | 152 | adapter->link_speed = ret >> 16; |
149 | if (ret & 1) { /* Link is up. */ | 153 | if (ret & 1) { /* Link is up. */ |
150 | printk(KERN_INFO "%s: NIC Link is Up %d Mbps\n", | 154 | printk(KERN_INFO "%s: NIC Link is Up %d Mbps\n", |
@@ -186,8 +190,10 @@ vmxnet3_process_events(struct vmxnet3_adapter *adapter) | |||
186 | 190 | ||
187 | /* Check if there is an error on xmit/recv queues */ | 191 | /* Check if there is an error on xmit/recv queues */ |
188 | if (events & (VMXNET3_ECR_TQERR | VMXNET3_ECR_RQERR)) { | 192 | if (events & (VMXNET3_ECR_TQERR | VMXNET3_ECR_RQERR)) { |
193 | spin_lock(&adapter->cmd_lock); | ||
189 | VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, | 194 | VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, |
190 | VMXNET3_CMD_GET_QUEUE_STATUS); | 195 | VMXNET3_CMD_GET_QUEUE_STATUS); |
196 | spin_unlock(&adapter->cmd_lock); | ||
191 | 197 | ||
192 | for (i = 0; i < adapter->num_tx_queues; i++) | 198 | for (i = 0; i < adapter->num_tx_queues; i++) |
193 | if (adapter->tqd_start[i].status.stopped) | 199 | if (adapter->tqd_start[i].status.stopped) |
@@ -1857,6 +1863,7 @@ vmxnet3_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) | |||
1857 | struct vmxnet3_adapter *adapter = netdev_priv(netdev); | 1863 | struct vmxnet3_adapter *adapter = netdev_priv(netdev); |
1858 | struct Vmxnet3_DriverShared *shared = adapter->shared; | 1864 | struct Vmxnet3_DriverShared *shared = adapter->shared; |
1859 | u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable; | 1865 | u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable; |
1866 | unsigned long flags; | ||
1860 | 1867 | ||
1861 | if (grp) { | 1868 | if (grp) { |
1862 | /* add vlan rx stripping. */ | 1869 | /* add vlan rx stripping. */ |
@@ -1873,8 +1880,10 @@ vmxnet3_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) | |||
1873 | vfTable[i] = 0; | 1880 | vfTable[i] = 0; |
1874 | 1881 | ||
1875 | VMXNET3_SET_VFTABLE_ENTRY(vfTable, 0); | 1882 | VMXNET3_SET_VFTABLE_ENTRY(vfTable, 0); |
1883 | spin_lock_irqsave(&adapter->cmd_lock, flags); | ||
1876 | VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, | 1884 | VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, |
1877 | VMXNET3_CMD_UPDATE_VLAN_FILTERS); | 1885 | VMXNET3_CMD_UPDATE_VLAN_FILTERS); |
1886 | spin_unlock_irqrestore(&adapter->cmd_lock, flags); | ||
1878 | } else { | 1887 | } else { |
1879 | printk(KERN_ERR "%s: vlan_rx_register when device has " | 1888 | printk(KERN_ERR "%s: vlan_rx_register when device has " |
1880 | "no NETIF_F_HW_VLAN_RX\n", netdev->name); | 1889 | "no NETIF_F_HW_VLAN_RX\n", netdev->name); |
@@ -1893,8 +1902,10 @@ vmxnet3_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) | |||
1893 | */ | 1902 | */ |
1894 | vfTable[i] = 0; | 1903 | vfTable[i] = 0; |
1895 | } | 1904 | } |
1905 | spin_lock_irqsave(&adapter->cmd_lock, flags); | ||
1896 | VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, | 1906 | VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, |
1897 | VMXNET3_CMD_UPDATE_VLAN_FILTERS); | 1907 | VMXNET3_CMD_UPDATE_VLAN_FILTERS); |
1908 | spin_unlock_irqrestore(&adapter->cmd_lock, flags); | ||
1898 | } | 1909 | } |
1899 | } | 1910 | } |
1900 | } | 1911 | } |
@@ -1927,10 +1938,13 @@ vmxnet3_vlan_rx_add_vid(struct net_device *netdev, u16 vid) | |||
1927 | { | 1938 | { |
1928 | struct vmxnet3_adapter *adapter = netdev_priv(netdev); | 1939 | struct vmxnet3_adapter *adapter = netdev_priv(netdev); |
1929 | u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable; | 1940 | u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable; |
1941 | unsigned long flags; | ||
1930 | 1942 | ||
1931 | VMXNET3_SET_VFTABLE_ENTRY(vfTable, vid); | 1943 | VMXNET3_SET_VFTABLE_ENTRY(vfTable, vid); |
1944 | spin_lock_irqsave(&adapter->cmd_lock, flags); | ||
1932 | VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, | 1945 | VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, |
1933 | VMXNET3_CMD_UPDATE_VLAN_FILTERS); | 1946 | VMXNET3_CMD_UPDATE_VLAN_FILTERS); |
1947 | spin_unlock_irqrestore(&adapter->cmd_lock, flags); | ||
1934 | } | 1948 | } |
1935 | 1949 | ||
1936 | 1950 | ||
@@ -1939,10 +1953,13 @@ vmxnet3_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) | |||
1939 | { | 1953 | { |
1940 | struct vmxnet3_adapter *adapter = netdev_priv(netdev); | 1954 | struct vmxnet3_adapter *adapter = netdev_priv(netdev); |
1941 | u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable; | 1955 | u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable; |
1956 | unsigned long flags; | ||
1942 | 1957 | ||
1943 | VMXNET3_CLEAR_VFTABLE_ENTRY(vfTable, vid); | 1958 | VMXNET3_CLEAR_VFTABLE_ENTRY(vfTable, vid); |
1959 | spin_lock_irqsave(&adapter->cmd_lock, flags); | ||
1944 | VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, | 1960 | VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, |
1945 | VMXNET3_CMD_UPDATE_VLAN_FILTERS); | 1961 | VMXNET3_CMD_UPDATE_VLAN_FILTERS); |
1962 | spin_unlock_irqrestore(&adapter->cmd_lock, flags); | ||
1946 | } | 1963 | } |
1947 | 1964 | ||
1948 | 1965 | ||
@@ -1973,6 +1990,7 @@ static void | |||
1973 | vmxnet3_set_mc(struct net_device *netdev) | 1990 | vmxnet3_set_mc(struct net_device *netdev) |
1974 | { | 1991 | { |
1975 | struct vmxnet3_adapter *adapter = netdev_priv(netdev); | 1992 | struct vmxnet3_adapter *adapter = netdev_priv(netdev); |
1993 | unsigned long flags; | ||
1976 | struct Vmxnet3_RxFilterConf *rxConf = | 1994 | struct Vmxnet3_RxFilterConf *rxConf = |
1977 | &adapter->shared->devRead.rxFilterConf; | 1995 | &adapter->shared->devRead.rxFilterConf; |
1978 | u8 *new_table = NULL; | 1996 | u8 *new_table = NULL; |
@@ -2008,6 +2026,7 @@ vmxnet3_set_mc(struct net_device *netdev) | |||
2008 | rxConf->mfTablePA = 0; | 2026 | rxConf->mfTablePA = 0; |
2009 | } | 2027 | } |
2010 | 2028 | ||
2029 | spin_lock_irqsave(&adapter->cmd_lock, flags); | ||
2011 | if (new_mode != rxConf->rxMode) { | 2030 | if (new_mode != rxConf->rxMode) { |
2012 | rxConf->rxMode = cpu_to_le32(new_mode); | 2031 | rxConf->rxMode = cpu_to_le32(new_mode); |
2013 | VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, | 2032 | VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, |
@@ -2016,6 +2035,7 @@ vmxnet3_set_mc(struct net_device *netdev) | |||
2016 | 2035 | ||
2017 | VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, | 2036 | VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, |
2018 | VMXNET3_CMD_UPDATE_MAC_FILTERS); | 2037 | VMXNET3_CMD_UPDATE_MAC_FILTERS); |
2038 | spin_unlock_irqrestore(&adapter->cmd_lock, flags); | ||
2019 | 2039 | ||
2020 | kfree(new_table); | 2040 | kfree(new_table); |
2021 | } | 2041 | } |
@@ -2165,6 +2185,7 @@ vmxnet3_activate_dev(struct vmxnet3_adapter *adapter) | |||
2165 | { | 2185 | { |
2166 | int err, i; | 2186 | int err, i; |
2167 | u32 ret; | 2187 | u32 ret; |
2188 | unsigned long flags; | ||
2168 | 2189 | ||
2169 | dev_dbg(&adapter->netdev->dev, "%s: skb_buf_size %d, rx_buf_per_pkt %d," | 2190 | dev_dbg(&adapter->netdev->dev, "%s: skb_buf_size %d, rx_buf_per_pkt %d," |
2170 | " ring sizes %u %u %u\n", adapter->netdev->name, | 2191 | " ring sizes %u %u %u\n", adapter->netdev->name, |
@@ -2194,9 +2215,11 @@ vmxnet3_activate_dev(struct vmxnet3_adapter *adapter) | |||
2194 | adapter->shared_pa)); | 2215 | adapter->shared_pa)); |
2195 | VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_DSAH, VMXNET3_GET_ADDR_HI( | 2216 | VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_DSAH, VMXNET3_GET_ADDR_HI( |
2196 | adapter->shared_pa)); | 2217 | adapter->shared_pa)); |
2218 | spin_lock_irqsave(&adapter->cmd_lock, flags); | ||
2197 | VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, | 2219 | VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, |
2198 | VMXNET3_CMD_ACTIVATE_DEV); | 2220 | VMXNET3_CMD_ACTIVATE_DEV); |
2199 | ret = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD); | 2221 | ret = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD); |
2222 | spin_unlock_irqrestore(&adapter->cmd_lock, flags); | ||
2200 | 2223 | ||
2201 | if (ret != 0) { | 2224 | if (ret != 0) { |
2202 | printk(KERN_ERR "Failed to activate dev %s: error %u\n", | 2225 | printk(KERN_ERR "Failed to activate dev %s: error %u\n", |
@@ -2243,7 +2266,10 @@ rq_err: | |||
2243 | void | 2266 | void |
2244 | vmxnet3_reset_dev(struct vmxnet3_adapter *adapter) | 2267 | vmxnet3_reset_dev(struct vmxnet3_adapter *adapter) |
2245 | { | 2268 | { |
2269 | unsigned long flags; | ||
2270 | spin_lock_irqsave(&adapter->cmd_lock, flags); | ||
2246 | VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_CMD_RESET_DEV); | 2271 | VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_CMD_RESET_DEV); |
2272 | spin_unlock_irqrestore(&adapter->cmd_lock, flags); | ||
2247 | } | 2273 | } |
2248 | 2274 | ||
2249 | 2275 | ||
@@ -2251,12 +2277,15 @@ int | |||
2251 | vmxnet3_quiesce_dev(struct vmxnet3_adapter *adapter) | 2277 | vmxnet3_quiesce_dev(struct vmxnet3_adapter *adapter) |
2252 | { | 2278 | { |
2253 | int i; | 2279 | int i; |
2280 | unsigned long flags; | ||
2254 | if (test_and_set_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state)) | 2281 | if (test_and_set_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state)) |
2255 | return 0; | 2282 | return 0; |
2256 | 2283 | ||
2257 | 2284 | ||
2285 | spin_lock_irqsave(&adapter->cmd_lock, flags); | ||
2258 | VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, | 2286 | VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, |
2259 | VMXNET3_CMD_QUIESCE_DEV); | 2287 | VMXNET3_CMD_QUIESCE_DEV); |
2288 | spin_unlock_irqrestore(&adapter->cmd_lock, flags); | ||
2260 | vmxnet3_disable_all_intrs(adapter); | 2289 | vmxnet3_disable_all_intrs(adapter); |
2261 | 2290 | ||
2262 | for (i = 0; i < adapter->num_rx_queues; i++) | 2291 | for (i = 0; i < adapter->num_rx_queues; i++) |
@@ -2706,9 +2735,11 @@ vmxnet3_alloc_intr_resources(struct vmxnet3_adapter *adapter) | |||
2706 | u32 cfg; | 2735 | u32 cfg; |
2707 | 2736 | ||
2708 | /* intr settings */ | 2737 | /* intr settings */ |
2738 | spin_lock(&adapter->cmd_lock); | ||
2709 | VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, | 2739 | VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, |
2710 | VMXNET3_CMD_GET_CONF_INTR); | 2740 | VMXNET3_CMD_GET_CONF_INTR); |
2711 | cfg = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD); | 2741 | cfg = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD); |
2742 | spin_unlock(&adapter->cmd_lock); | ||
2712 | adapter->intr.type = cfg & 0x3; | 2743 | adapter->intr.type = cfg & 0x3; |
2713 | adapter->intr.mask_mode = (cfg >> 2) & 0x3; | 2744 | adapter->intr.mask_mode = (cfg >> 2) & 0x3; |
2714 | 2745 | ||
@@ -2893,6 +2924,7 @@ vmxnet3_probe_device(struct pci_dev *pdev, | |||
2893 | adapter->netdev = netdev; | 2924 | adapter->netdev = netdev; |
2894 | adapter->pdev = pdev; | 2925 | adapter->pdev = pdev; |
2895 | 2926 | ||
2927 | spin_lock_init(&adapter->cmd_lock); | ||
2896 | adapter->shared = pci_alloc_consistent(adapter->pdev, | 2928 | adapter->shared = pci_alloc_consistent(adapter->pdev, |
2897 | sizeof(struct Vmxnet3_DriverShared), | 2929 | sizeof(struct Vmxnet3_DriverShared), |
2898 | &adapter->shared_pa); | 2930 | &adapter->shared_pa); |
@@ -3096,6 +3128,7 @@ vmxnet3_suspend(struct device *device) | |||
3096 | u8 *arpreq; | 3128 | u8 *arpreq; |
3097 | struct in_device *in_dev; | 3129 | struct in_device *in_dev; |
3098 | struct in_ifaddr *ifa; | 3130 | struct in_ifaddr *ifa; |
3131 | unsigned long flags; | ||
3099 | int i = 0; | 3132 | int i = 0; |
3100 | 3133 | ||
3101 | if (!netif_running(netdev)) | 3134 | if (!netif_running(netdev)) |
@@ -3179,8 +3212,10 @@ skip_arp: | |||
3179 | adapter->shared->devRead.pmConfDesc.confPA = cpu_to_le64(virt_to_phys( | 3212 | adapter->shared->devRead.pmConfDesc.confPA = cpu_to_le64(virt_to_phys( |
3180 | pmConf)); | 3213 | pmConf)); |
3181 | 3214 | ||
3215 | spin_lock_irqsave(&adapter->cmd_lock, flags); | ||
3182 | VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, | 3216 | VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, |
3183 | VMXNET3_CMD_UPDATE_PMCFG); | 3217 | VMXNET3_CMD_UPDATE_PMCFG); |
3218 | spin_unlock_irqrestore(&adapter->cmd_lock, flags); | ||
3184 | 3219 | ||
3185 | pci_save_state(pdev); | 3220 | pci_save_state(pdev); |
3186 | pci_enable_wake(pdev, pci_choose_state(pdev, PMSG_SUSPEND), | 3221 | pci_enable_wake(pdev, pci_choose_state(pdev, PMSG_SUSPEND), |
@@ -3196,6 +3231,7 @@ static int | |||
3196 | vmxnet3_resume(struct device *device) | 3231 | vmxnet3_resume(struct device *device) |
3197 | { | 3232 | { |
3198 | int err, i = 0; | 3233 | int err, i = 0; |
3234 | unsigned long flags; | ||
3199 | struct pci_dev *pdev = to_pci_dev(device); | 3235 | struct pci_dev *pdev = to_pci_dev(device); |
3200 | struct net_device *netdev = pci_get_drvdata(pdev); | 3236 | struct net_device *netdev = pci_get_drvdata(pdev); |
3201 | struct vmxnet3_adapter *adapter = netdev_priv(netdev); | 3237 | struct vmxnet3_adapter *adapter = netdev_priv(netdev); |
@@ -3223,8 +3259,10 @@ vmxnet3_resume(struct device *device) | |||
3223 | 3259 | ||
3224 | pci_enable_wake(pdev, PCI_D0, 0); | 3260 | pci_enable_wake(pdev, PCI_D0, 0); |
3225 | 3261 | ||
3262 | spin_lock_irqsave(&adapter->cmd_lock, flags); | ||
3226 | VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, | 3263 | VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, |
3227 | VMXNET3_CMD_UPDATE_PMCFG); | 3264 | VMXNET3_CMD_UPDATE_PMCFG); |
3265 | spin_unlock_irqrestore(&adapter->cmd_lock, flags); | ||
3228 | vmxnet3_alloc_intr_resources(adapter); | 3266 | vmxnet3_alloc_intr_resources(adapter); |
3229 | vmxnet3_request_irqs(adapter); | 3267 | vmxnet3_request_irqs(adapter); |
3230 | for (i = 0; i < adapter->num_rx_queues; i++) | 3268 | for (i = 0; i < adapter->num_rx_queues; i++) |