aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/3c59x.c
diff options
context:
space:
mode:
authorBen Hutchings <ben@decadent.org.uk>2010-06-29 11:26:56 -0400
committerDavid S. Miller <davem@davemloft.net>2010-06-30 02:14:21 -0400
commitde847272149365363a6043a963a6f42fb91566e2 (patch)
tree51a1c4bbf9baec1d9949816734a869706a9b48cf /drivers/net/3c59x.c
parent5a86f28f954c3841d3a6df4d07d2ed17088c3711 (diff)
3c59x: Use fine-grained locks for MII and windowed register access
This avoids scheduling in atomic context and also means that IRQs will only be deferred for relatively short periods of time. Previously discussed in: http://article.gmane.org/gmane.linux.network/155024 Reported-by: Arne Nordmark <nordmark@mech.kth.se> Signed-off-by: Ben Hutchings <ben@decadent.org.uk> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/3c59x.c')
-rw-r--r--drivers/net/3c59x.c68
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
652static void window_set(struct vortex_private *vp, int window) 658static void window_set(struct vortex_private *vp, int window)
@@ -661,15 +667,23 @@ static void window_set(struct vortex_private *vp, int window)
661static u ## size \ 667static u ## size \
662window_read ## size(struct vortex_private *vp, int window, int addr) \ 668window_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} \
667static void \ 678static void \
668window_write ## size(struct vortex_private *vp, u ## size value, \ 679window_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}
674DEFINE_WINDOW_IO(8) 688DEFINE_WINDOW_IO(8)
675DEFINE_WINDOW_IO(16) 689DEFINE_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
1860leave_media_alone: 1876leave_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)
2806static int vortex_nway_reset(struct net_device *dev) 2826static 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
2818static int vortex_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) 2833static 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
2830static int vortex_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) 2840static 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
2842static u32 vortex_get_msglevel(struct net_device *dev) 2847static 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. */