aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/skge.c
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@osdl.org>2006-06-06 13:11:11 -0400
committerJeff Garzik <jeff@garzik.org>2006-06-08 15:44:54 -0400
commitd85b514fd9aa95d2089fa16dccc25863fb2a766c (patch)
tree7a46eaf6bfa9d745e821cedc51d9deb81b2d7108 /drivers/net/skge.c
parentb10c066823c97c0e40989b2048540e85f5190501 (diff)
[PATCH] skge: use workq for PHY handling
Since accessing the PHY can take 100's of usecs, use a work queue to allow spinning in outside of soft/hard irq. Signed-off-by: Stephen Hemminger <shemminger@osdl.org> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/skge.c')
-rw-r--r--drivers/net/skge.c46
1 files changed, 23 insertions, 23 deletions
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index 5ca5a1b546a1..55245dbaecbc 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -603,7 +603,7 @@ static void skge_led(struct skge_port *skge, enum led_mode mode)
603 struct skge_hw *hw = skge->hw; 603 struct skge_hw *hw = skge->hw;
604 int port = skge->port; 604 int port = skge->port;
605 605
606 spin_lock_bh(&hw->phy_lock); 606 mutex_lock(&hw->phy_mutex);
607 if (hw->chip_id == CHIP_ID_GENESIS) { 607 if (hw->chip_id == CHIP_ID_GENESIS) {
608 switch (mode) { 608 switch (mode) {
609 case LED_MODE_OFF: 609 case LED_MODE_OFF:
@@ -663,7 +663,7 @@ static void skge_led(struct skge_port *skge, enum led_mode mode)
663 PHY_M_LED_MO_RX(MO_LED_ON)); 663 PHY_M_LED_MO_RX(MO_LED_ON));
664 } 664 }
665 } 665 }
666 spin_unlock_bh(&hw->phy_lock); 666 mutex_unlock(&hw->phy_mutex);
667} 667}
668 668
669/* blink LED's for finding board */ 669/* blink LED's for finding board */
@@ -2038,7 +2038,7 @@ static void skge_phy_reset(struct skge_port *skge)
2038 netif_stop_queue(skge->netdev); 2038 netif_stop_queue(skge->netdev);
2039 netif_carrier_off(skge->netdev); 2039 netif_carrier_off(skge->netdev);
2040 2040
2041 spin_lock_bh(&hw->phy_lock); 2041 mutex_lock(&hw->phy_mutex);
2042 if (hw->chip_id == CHIP_ID_GENESIS) { 2042 if (hw->chip_id == CHIP_ID_GENESIS) {
2043 genesis_reset(hw, port); 2043 genesis_reset(hw, port);
2044 genesis_mac_init(hw, port); 2044 genesis_mac_init(hw, port);
@@ -2046,7 +2046,7 @@ static void skge_phy_reset(struct skge_port *skge)
2046 yukon_reset(hw, port); 2046 yukon_reset(hw, port);
2047 yukon_init(hw, port); 2047 yukon_init(hw, port);
2048 } 2048 }
2049 spin_unlock_bh(&hw->phy_lock); 2049 mutex_unlock(&hw->phy_mutex);
2050} 2050}
2051 2051
2052/* Basic MII support */ 2052/* Basic MII support */
@@ -2067,12 +2067,12 @@ static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
2067 /* fallthru */ 2067 /* fallthru */
2068 case SIOCGMIIREG: { 2068 case SIOCGMIIREG: {
2069 u16 val = 0; 2069 u16 val = 0;
2070 spin_lock_bh(&hw->phy_lock); 2070 mutex_lock(&hw->phy_mutex);
2071 if (hw->chip_id == CHIP_ID_GENESIS) 2071 if (hw->chip_id == CHIP_ID_GENESIS)
2072 err = __xm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val); 2072 err = __xm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val);
2073 else 2073 else
2074 err = __gm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val); 2074 err = __gm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val);
2075 spin_unlock_bh(&hw->phy_lock); 2075 mutex_unlock(&hw->phy_mutex);
2076 data->val_out = val; 2076 data->val_out = val;
2077 break; 2077 break;
2078 } 2078 }
@@ -2081,14 +2081,14 @@ static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
2081 if (!capable(CAP_NET_ADMIN)) 2081 if (!capable(CAP_NET_ADMIN))
2082 return -EPERM; 2082 return -EPERM;
2083 2083
2084 spin_lock_bh(&hw->phy_lock); 2084 mutex_lock(&hw->phy_mutex);
2085 if (hw->chip_id == CHIP_ID_GENESIS) 2085 if (hw->chip_id == CHIP_ID_GENESIS)
2086 err = xm_phy_write(hw, skge->port, data->reg_num & 0x1f, 2086 err = xm_phy_write(hw, skge->port, data->reg_num & 0x1f,
2087 data->val_in); 2087 data->val_in);
2088 else 2088 else
2089 err = gm_phy_write(hw, skge->port, data->reg_num & 0x1f, 2089 err = gm_phy_write(hw, skge->port, data->reg_num & 0x1f,
2090 data->val_in); 2090 data->val_in);
2091 spin_unlock_bh(&hw->phy_lock); 2091 mutex_unlock(&hw->phy_mutex);
2092 break; 2092 break;
2093 } 2093 }
2094 return err; 2094 return err;
@@ -2191,12 +2191,12 @@ static int skge_up(struct net_device *dev)
2191 goto free_rx_ring; 2191 goto free_rx_ring;
2192 2192
2193 /* Initialize MAC */ 2193 /* Initialize MAC */
2194 spin_lock_bh(&hw->phy_lock); 2194 mutex_lock(&hw->phy_mutex);
2195 if (hw->chip_id == CHIP_ID_GENESIS) 2195 if (hw->chip_id == CHIP_ID_GENESIS)
2196 genesis_mac_init(hw, port); 2196 genesis_mac_init(hw, port);
2197 else 2197 else
2198 yukon_mac_init(hw, port); 2198 yukon_mac_init(hw, port);
2199 spin_unlock_bh(&hw->phy_lock); 2199 mutex_unlock(&hw->phy_mutex);
2200 2200
2201 /* Configure RAMbuffers */ 2201 /* Configure RAMbuffers */
2202 chunk = hw->ram_size / ((hw->ports + 1)*2); 2202 chunk = hw->ram_size / ((hw->ports + 1)*2);
@@ -2847,16 +2847,16 @@ static void skge_error_irq(struct skge_hw *hw)
2847} 2847}
2848 2848
2849/* 2849/*
2850 * Interrupt from PHY are handled in tasklet (soft irq) 2850 * Interrupt from PHY are handled in work queue
2851 * because accessing phy registers requires spin wait which might 2851 * because accessing phy registers requires spin wait which might
2852 * cause excess interrupt latency. 2852 * cause excess interrupt latency.
2853 */ 2853 */
2854static void skge_extirq(unsigned long data) 2854static void skge_extirq(void *arg)
2855{ 2855{
2856 struct skge_hw *hw = (struct skge_hw *) data; 2856 struct skge_hw *hw = arg;
2857 int port; 2857 int port;
2858 2858
2859 spin_lock(&hw->phy_lock); 2859 mutex_lock(&hw->phy_mutex);
2860 for (port = 0; port < hw->ports; port++) { 2860 for (port = 0; port < hw->ports; port++) {
2861 struct net_device *dev = hw->dev[port]; 2861 struct net_device *dev = hw->dev[port];
2862 struct skge_port *skge = netdev_priv(dev); 2862 struct skge_port *skge = netdev_priv(dev);
@@ -2868,7 +2868,7 @@ static void skge_extirq(unsigned long data)
2868 bcom_phy_intr(skge); 2868 bcom_phy_intr(skge);
2869 } 2869 }
2870 } 2870 }
2871 spin_unlock(&hw->phy_lock); 2871 mutex_unlock(&hw->phy_mutex);
2872 2872
2873 hw->intr_mask |= IS_EXT_REG; 2873 hw->intr_mask |= IS_EXT_REG;
2874 skge_write32(hw, B0_IMSK, hw->intr_mask); 2874 skge_write32(hw, B0_IMSK, hw->intr_mask);
@@ -2886,7 +2886,7 @@ static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs)
2886 2886
2887 if (status & IS_EXT_REG) { 2887 if (status & IS_EXT_REG) {
2888 hw->intr_mask &= ~IS_EXT_REG; 2888 hw->intr_mask &= ~IS_EXT_REG;
2889 tasklet_schedule(&hw->ext_tasklet); 2889 schedule_work(&hw->phy_work);
2890 } 2890 }
2891 2891
2892 if (status & (IS_R1_F|IS_XA1_F)) { 2892 if (status & (IS_R1_F|IS_XA1_F)) {
@@ -2957,7 +2957,7 @@ static int skge_set_mac_address(struct net_device *dev, void *p)
2957 if (!is_valid_ether_addr(addr->sa_data)) 2957 if (!is_valid_ether_addr(addr->sa_data))
2958 return -EADDRNOTAVAIL; 2958 return -EADDRNOTAVAIL;
2959 2959
2960 spin_lock_bh(&hw->phy_lock); 2960 mutex_lock(&hw->phy_mutex);
2961 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); 2961 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
2962 memcpy_toio(hw->regs + B2_MAC_1 + port*8, 2962 memcpy_toio(hw->regs + B2_MAC_1 + port*8,
2963 dev->dev_addr, ETH_ALEN); 2963 dev->dev_addr, ETH_ALEN);
@@ -2970,7 +2970,7 @@ static int skge_set_mac_address(struct net_device *dev, void *p)
2970 gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr); 2970 gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr);
2971 gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr); 2971 gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr);
2972 } 2972 }
2973 spin_unlock_bh(&hw->phy_lock); 2973 mutex_unlock(&hw->phy_mutex);
2974 2974
2975 return 0; 2975 return 0;
2976} 2976}
@@ -3150,14 +3150,14 @@ static int skge_reset(struct skge_hw *hw)
3150 3150
3151 skge_write32(hw, B0_IMSK, hw->intr_mask); 3151 skge_write32(hw, B0_IMSK, hw->intr_mask);
3152 3152
3153 spin_lock_bh(&hw->phy_lock); 3153 mutex_lock(&hw->phy_mutex);
3154 for (i = 0; i < hw->ports; i++) { 3154 for (i = 0; i < hw->ports; i++) {
3155 if (hw->chip_id == CHIP_ID_GENESIS) 3155 if (hw->chip_id == CHIP_ID_GENESIS)
3156 genesis_reset(hw, i); 3156 genesis_reset(hw, i);
3157 else 3157 else
3158 yukon_reset(hw, i); 3158 yukon_reset(hw, i);
3159 } 3159 }
3160 spin_unlock_bh(&hw->phy_lock); 3160 mutex_unlock(&hw->phy_mutex);
3161 3161
3162 return 0; 3162 return 0;
3163} 3163}
@@ -3305,8 +3305,8 @@ static int __devinit skge_probe(struct pci_dev *pdev,
3305 } 3305 }
3306 3306
3307 hw->pdev = pdev; 3307 hw->pdev = pdev;
3308 spin_lock_init(&hw->phy_lock); 3308 mutex_init(&hw->phy_mutex);
3309 tasklet_init(&hw->ext_tasklet, skge_extirq, (unsigned long) hw); 3309 INIT_WORK(&hw->phy_work, skge_extirq, hw);
3310 3310
3311 hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000); 3311 hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000);
3312 if (!hw->regs) { 3312 if (!hw->regs) {
@@ -3392,7 +3392,7 @@ static void __devexit skge_remove(struct pci_dev *pdev)
3392 skge_write16(hw, B0_LED, LED_STAT_OFF); 3392 skge_write16(hw, B0_LED, LED_STAT_OFF);
3393 skge_write8(hw, B0_CTST, CS_RST_SET); 3393 skge_write8(hw, B0_CTST, CS_RST_SET);
3394 3394
3395 tasklet_kill(&hw->ext_tasklet); 3395 flush_scheduled_work();
3396 3396
3397 free_irq(pdev->irq, hw); 3397 free_irq(pdev->irq, hw);
3398 pci_release_regions(pdev); 3398 pci_release_regions(pdev);