diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/3c59x.c | 68 |
1 files changed, 41 insertions, 27 deletions
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index beddef98ad92..069a03f717d3 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c | |||
@@ -644,9 +644,15 @@ struct vortex_private { | |||
644 | u16 deferred; /* Resend these interrupts when we | 644 | u16 deferred; /* Resend these interrupts when we |
645 | * bale from the ISR */ | 645 | * bale from the ISR */ |
646 | u16 io_size; /* Size of PCI region (for release_region) */ | 646 | u16 io_size; /* Size of PCI region (for release_region) */ |
647 | spinlock_t lock; /* Serialise access to device & its vortex_private */ | 647 | |
648 | struct mii_if_info mii; /* MII lib hooks/info */ | 648 | /* Serialises access to hardware other than MII and variables below. |
649 | int window; /* Register window */ | 649 | * The lock hierarchy is rtnl_lock > lock > mii_lock > window_lock. */ |
650 | spinlock_t lock; | ||
651 | |||
652 | spinlock_t mii_lock; /* Serialises access to MII */ | ||
653 | struct mii_if_info mii; /* MII lib hooks/info */ | ||
654 | spinlock_t window_lock; /* Serialises access to windowed regs */ | ||
655 | int window; /* Register window */ | ||
650 | }; | 656 | }; |
651 | 657 | ||
652 | static void window_set(struct vortex_private *vp, int window) | 658 | static void window_set(struct vortex_private *vp, int window) |
@@ -661,15 +667,23 @@ static void window_set(struct vortex_private *vp, int window) | |||
661 | static u ## size \ | 667 | static u ## size \ |
662 | window_read ## size(struct vortex_private *vp, int window, int addr) \ | 668 | window_read ## size(struct vortex_private *vp, int window, int addr) \ |
663 | { \ | 669 | { \ |
670 | unsigned long flags; \ | ||
671 | u ## size ret; \ | ||
672 | spin_lock_irqsave(&vp->window_lock, flags); \ | ||
664 | window_set(vp, window); \ | 673 | window_set(vp, window); \ |
665 | return ioread ## size(vp->ioaddr + addr); \ | 674 | ret = ioread ## size(vp->ioaddr + addr); \ |
675 | spin_unlock_irqrestore(&vp->window_lock, flags); \ | ||
676 | return ret; \ | ||
666 | } \ | 677 | } \ |
667 | static void \ | 678 | static void \ |
668 | window_write ## size(struct vortex_private *vp, u ## size value, \ | 679 | window_write ## size(struct vortex_private *vp, u ## size value, \ |
669 | int window, int addr) \ | 680 | int window, int addr) \ |
670 | { \ | 681 | { \ |
682 | unsigned long flags; \ | ||
683 | spin_lock_irqsave(&vp->window_lock, flags); \ | ||
671 | window_set(vp, window); \ | 684 | window_set(vp, window); \ |
672 | iowrite ## size(value, vp->ioaddr + addr); \ | 685 | iowrite ## size(value, vp->ioaddr + addr); \ |
686 | spin_unlock_irqrestore(&vp->window_lock, flags); \ | ||
673 | } | 687 | } |
674 | DEFINE_WINDOW_IO(8) | 688 | DEFINE_WINDOW_IO(8) |
675 | DEFINE_WINDOW_IO(16) | 689 | DEFINE_WINDOW_IO(16) |
@@ -1181,6 +1195,8 @@ static int __devinit vortex_probe1(struct device *gendev, | |||
1181 | } | 1195 | } |
1182 | 1196 | ||
1183 | spin_lock_init(&vp->lock); | 1197 | spin_lock_init(&vp->lock); |
1198 | spin_lock_init(&vp->mii_lock); | ||
1199 | spin_lock_init(&vp->window_lock); | ||
1184 | vp->gendev = gendev; | 1200 | vp->gendev = gendev; |
1185 | vp->mii.dev = dev; | 1201 | vp->mii.dev = dev; |
1186 | vp->mii.mdio_read = mdio_read; | 1202 | vp->mii.mdio_read = mdio_read; |
@@ -1784,7 +1800,6 @@ vortex_timer(unsigned long data) | |||
1784 | pr_debug("dev->watchdog_timeo=%d\n", dev->watchdog_timeo); | 1800 | pr_debug("dev->watchdog_timeo=%d\n", dev->watchdog_timeo); |
1785 | } | 1801 | } |
1786 | 1802 | ||
1787 | disable_irq_lockdep(dev->irq); | ||
1788 | media_status = window_read16(vp, 4, Wn4_Media); | 1803 | media_status = window_read16(vp, 4, Wn4_Media); |
1789 | switch (dev->if_port) { | 1804 | switch (dev->if_port) { |
1790 | case XCVR_10baseT: case XCVR_100baseTx: case XCVR_100baseFx: | 1805 | case XCVR_10baseT: case XCVR_100baseTx: case XCVR_100baseFx: |
@@ -1805,10 +1820,7 @@ vortex_timer(unsigned long data) | |||
1805 | case XCVR_MII: case XCVR_NWAY: | 1820 | case XCVR_MII: case XCVR_NWAY: |
1806 | { | 1821 | { |
1807 | ok = 1; | 1822 | ok = 1; |
1808 | /* Interrupts are already disabled */ | ||
1809 | spin_lock(&vp->lock); | ||
1810 | vortex_check_media(dev, 0); | 1823 | vortex_check_media(dev, 0); |
1811 | spin_unlock(&vp->lock); | ||
1812 | } | 1824 | } |
1813 | break; | 1825 | break; |
1814 | default: /* Other media types handled by Tx timeouts. */ | 1826 | default: /* Other media types handled by Tx timeouts. */ |
@@ -1827,6 +1839,8 @@ vortex_timer(unsigned long data) | |||
1827 | if (!ok) { | 1839 | if (!ok) { |
1828 | unsigned int config; | 1840 | unsigned int config; |
1829 | 1841 | ||
1842 | spin_lock_irq(&vp->lock); | ||
1843 | |||
1830 | do { | 1844 | do { |
1831 | dev->if_port = media_tbl[dev->if_port].next; | 1845 | dev->if_port = media_tbl[dev->if_port].next; |
1832 | } while ( ! (vp->available_media & media_tbl[dev->if_port].mask)); | 1846 | } while ( ! (vp->available_media & media_tbl[dev->if_port].mask)); |
@@ -1855,6 +1869,8 @@ vortex_timer(unsigned long data) | |||
1855 | if (vortex_debug > 1) | 1869 | if (vortex_debug > 1) |
1856 | pr_debug("wrote 0x%08x to Wn3_Config\n", config); | 1870 | pr_debug("wrote 0x%08x to Wn3_Config\n", config); |
1857 | /* AKPM: FIXME: Should reset Rx & Tx here. P60 of 3c90xc.pdf */ | 1871 | /* AKPM: FIXME: Should reset Rx & Tx here. P60 of 3c90xc.pdf */ |
1872 | |||
1873 | spin_unlock_irq(&vp->lock); | ||
1858 | } | 1874 | } |
1859 | 1875 | ||
1860 | leave_media_alone: | 1876 | leave_media_alone: |
@@ -1862,7 +1878,6 @@ leave_media_alone: | |||
1862 | pr_debug("%s: Media selection timer finished, %s.\n", | 1878 | pr_debug("%s: Media selection timer finished, %s.\n", |
1863 | dev->name, media_tbl[dev->if_port].name); | 1879 | dev->name, media_tbl[dev->if_port].name); |
1864 | 1880 | ||
1865 | enable_irq_lockdep(dev->irq); | ||
1866 | mod_timer(&vp->timer, RUN_AT(next_tick)); | 1881 | mod_timer(&vp->timer, RUN_AT(next_tick)); |
1867 | if (vp->deferred) | 1882 | if (vp->deferred) |
1868 | iowrite16(FakeIntr, ioaddr + EL3_CMD); | 1883 | iowrite16(FakeIntr, ioaddr + EL3_CMD); |
@@ -2051,9 +2066,11 @@ vortex_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
2051 | int len = (skb->len + 3) & ~3; | 2066 | int len = (skb->len + 3) & ~3; |
2052 | vp->tx_skb_dma = pci_map_single(VORTEX_PCI(vp), skb->data, len, | 2067 | vp->tx_skb_dma = pci_map_single(VORTEX_PCI(vp), skb->data, len, |
2053 | PCI_DMA_TODEVICE); | 2068 | PCI_DMA_TODEVICE); |
2069 | spin_lock_irq(&vp->window_lock); | ||
2054 | window_set(vp, 7); | 2070 | window_set(vp, 7); |
2055 | iowrite32(vp->tx_skb_dma, ioaddr + Wn7_MasterAddr); | 2071 | iowrite32(vp->tx_skb_dma, ioaddr + Wn7_MasterAddr); |
2056 | iowrite16(len, ioaddr + Wn7_MasterLen); | 2072 | iowrite16(len, ioaddr + Wn7_MasterLen); |
2073 | spin_unlock_irq(&vp->window_lock); | ||
2057 | vp->tx_skb = skb; | 2074 | vp->tx_skb = skb; |
2058 | iowrite16(StartDMADown, ioaddr + EL3_CMD); | 2075 | iowrite16(StartDMADown, ioaddr + EL3_CMD); |
2059 | /* netif_wake_queue() will be called at the DMADone interrupt. */ | 2076 | /* netif_wake_queue() will be called at the DMADone interrupt. */ |
@@ -2225,6 +2242,7 @@ vortex_interrupt(int irq, void *dev_id) | |||
2225 | pr_debug("%s: interrupt, status %4.4x, latency %d ticks.\n", | 2242 | pr_debug("%s: interrupt, status %4.4x, latency %d ticks.\n", |
2226 | dev->name, status, ioread8(ioaddr + Timer)); | 2243 | dev->name, status, ioread8(ioaddr + Timer)); |
2227 | 2244 | ||
2245 | spin_lock(&vp->window_lock); | ||
2228 | window_set(vp, 7); | 2246 | window_set(vp, 7); |
2229 | 2247 | ||
2230 | do { | 2248 | do { |
@@ -2285,6 +2303,8 @@ vortex_interrupt(int irq, void *dev_id) | |||
2285 | iowrite16(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD); | 2303 | iowrite16(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD); |
2286 | } while ((status = ioread16(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete)); | 2304 | } while ((status = ioread16(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete)); |
2287 | 2305 | ||
2306 | spin_unlock(&vp->window_lock); | ||
2307 | |||
2288 | if (vortex_debug > 4) | 2308 | if (vortex_debug > 4) |
2289 | pr_debug("%s: exiting interrupt, status %4.4x.\n", | 2309 | pr_debug("%s: exiting interrupt, status %4.4x.\n", |
2290 | dev->name, status); | 2310 | dev->name, status); |
@@ -2806,37 +2826,22 @@ static void update_stats(void __iomem *ioaddr, struct net_device *dev) | |||
2806 | static int vortex_nway_reset(struct net_device *dev) | 2826 | static int vortex_nway_reset(struct net_device *dev) |
2807 | { | 2827 | { |
2808 | struct vortex_private *vp = netdev_priv(dev); | 2828 | struct vortex_private *vp = netdev_priv(dev); |
2809 | unsigned long flags; | ||
2810 | int rc; | ||
2811 | 2829 | ||
2812 | spin_lock_irqsave(&vp->lock, flags); | 2830 | return mii_nway_restart(&vp->mii); |
2813 | rc = mii_nway_restart(&vp->mii); | ||
2814 | spin_unlock_irqrestore(&vp->lock, flags); | ||
2815 | return rc; | ||
2816 | } | 2831 | } |
2817 | 2832 | ||
2818 | static int vortex_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | 2833 | static int vortex_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) |
2819 | { | 2834 | { |
2820 | struct vortex_private *vp = netdev_priv(dev); | 2835 | struct vortex_private *vp = netdev_priv(dev); |
2821 | unsigned long flags; | ||
2822 | int rc; | ||
2823 | 2836 | ||
2824 | spin_lock_irqsave(&vp->lock, flags); | 2837 | return mii_ethtool_gset(&vp->mii, cmd); |
2825 | rc = mii_ethtool_gset(&vp->mii, cmd); | ||
2826 | spin_unlock_irqrestore(&vp->lock, flags); | ||
2827 | return rc; | ||
2828 | } | 2838 | } |
2829 | 2839 | ||
2830 | static int vortex_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | 2840 | static int vortex_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) |
2831 | { | 2841 | { |
2832 | struct vortex_private *vp = netdev_priv(dev); | 2842 | struct vortex_private *vp = netdev_priv(dev); |
2833 | unsigned long flags; | ||
2834 | int rc; | ||
2835 | 2843 | ||
2836 | spin_lock_irqsave(&vp->lock, flags); | 2844 | return mii_ethtool_sset(&vp->mii, cmd); |
2837 | rc = mii_ethtool_sset(&vp->mii, cmd); | ||
2838 | spin_unlock_irqrestore(&vp->lock, flags); | ||
2839 | return rc; | ||
2840 | } | 2845 | } |
2841 | 2846 | ||
2842 | static u32 vortex_get_msglevel(struct net_device *dev) | 2847 | static u32 vortex_get_msglevel(struct net_device *dev) |
@@ -3059,6 +3064,8 @@ static int mdio_read(struct net_device *dev, int phy_id, int location) | |||
3059 | int read_cmd = (0xf6 << 10) | (phy_id << 5) | location; | 3064 | int read_cmd = (0xf6 << 10) | (phy_id << 5) | location; |
3060 | unsigned int retval = 0; | 3065 | unsigned int retval = 0; |
3061 | 3066 | ||
3067 | spin_lock_bh(&vp->mii_lock); | ||
3068 | |||
3062 | if (mii_preamble_required) | 3069 | if (mii_preamble_required) |
3063 | mdio_sync(vp, 32); | 3070 | mdio_sync(vp, 32); |
3064 | 3071 | ||
@@ -3082,6 +3089,9 @@ static int mdio_read(struct net_device *dev, int phy_id, int location) | |||
3082 | 4, Wn4_PhysicalMgmt); | 3089 | 4, Wn4_PhysicalMgmt); |
3083 | mdio_delay(vp); | 3090 | mdio_delay(vp); |
3084 | } | 3091 | } |
3092 | |||
3093 | spin_unlock_bh(&vp->mii_lock); | ||
3094 | |||
3085 | return retval & 0x20000 ? 0xffff : retval>>1 & 0xffff; | 3095 | return retval & 0x20000 ? 0xffff : retval>>1 & 0xffff; |
3086 | } | 3096 | } |
3087 | 3097 | ||
@@ -3091,6 +3101,8 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val | |||
3091 | int write_cmd = 0x50020000 | (phy_id << 23) | (location << 18) | value; | 3101 | int write_cmd = 0x50020000 | (phy_id << 23) | (location << 18) | value; |
3092 | int i; | 3102 | int i; |
3093 | 3103 | ||
3104 | spin_lock_bh(&vp->mii_lock); | ||
3105 | |||
3094 | if (mii_preamble_required) | 3106 | if (mii_preamble_required) |
3095 | mdio_sync(vp, 32); | 3107 | mdio_sync(vp, 32); |
3096 | 3108 | ||
@@ -3111,6 +3123,8 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val | |||
3111 | 4, Wn4_PhysicalMgmt); | 3123 | 4, Wn4_PhysicalMgmt); |
3112 | mdio_delay(vp); | 3124 | mdio_delay(vp); |
3113 | } | 3125 | } |
3126 | |||
3127 | spin_unlock_bh(&vp->mii_lock); | ||
3114 | } | 3128 | } |
3115 | 3129 | ||
3116 | /* ACPI: Advanced Configuration and Power Interface. */ | 3130 | /* ACPI: Advanced Configuration and Power Interface. */ |