|
@@ -105,7 +105,8 @@ static const int txqaddr[] = { Q_XA1, Q_XA2 };
|
|
static const int rxqaddr[] = { Q_R1, Q_R2 };
|
|
static const int rxqaddr[] = { Q_R1, Q_R2 };
|
|
static const u32 rxirqmask[] = { IS_R1_F, IS_R2_F };
|
|
static const u32 rxirqmask[] = { IS_R1_F, IS_R2_F };
|
|
static const u32 txirqmask[] = { IS_XA1_F, IS_XA2_F };
|
|
static const u32 txirqmask[] = { IS_XA1_F, IS_XA2_F };
|
|
-static const u32 irqmask[] = { IS_R1_F|IS_XA1_F, IS_R2_F|IS_XA2_F };
|
|
|
|
|
|
+static const u32 napimask[] = { IS_R1_F|IS_XA1_F, IS_R2_F|IS_XA2_F };
|
|
|
|
+static const u32 portmask[] = { IS_PORT_1, IS_PORT_2 };
|
|
|
|
|
|
static int skge_get_regs_len(struct net_device *dev)
|
|
static int skge_get_regs_len(struct net_device *dev)
|
|
{
|
|
{
|
|
@@ -671,7 +672,7 @@ static void skge_led(struct skge_port *skge, enum led_mode mode)
|
|
struct skge_hw *hw = skge->hw;
|
|
struct skge_hw *hw = skge->hw;
|
|
int port = skge->port;
|
|
int port = skge->port;
|
|
|
|
|
|
- mutex_lock(&hw->phy_mutex);
|
|
|
|
|
|
+ spin_lock_bh(&hw->phy_lock);
|
|
if (hw->chip_id == CHIP_ID_GENESIS) {
|
|
if (hw->chip_id == CHIP_ID_GENESIS) {
|
|
switch (mode) {
|
|
switch (mode) {
|
|
case LED_MODE_OFF:
|
|
case LED_MODE_OFF:
|
|
@@ -742,7 +743,7 @@ static void skge_led(struct skge_port *skge, enum led_mode mode)
|
|
PHY_M_LED_MO_RX(MO_LED_ON));
|
|
PHY_M_LED_MO_RX(MO_LED_ON));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- mutex_unlock(&hw->phy_mutex);
|
|
|
|
|
|
+ spin_unlock_bh(&hw->phy_lock);
|
|
}
|
|
}
|
|
|
|
|
|
/* blink LED's for finding board */
|
|
/* blink LED's for finding board */
|
|
@@ -1316,7 +1317,7 @@ static void xm_phy_init(struct skge_port *skge)
|
|
xm_phy_write(hw, port, PHY_XMAC_CTRL, ctrl);
|
|
xm_phy_write(hw, port, PHY_XMAC_CTRL, ctrl);
|
|
|
|
|
|
/* Poll PHY for status changes */
|
|
/* Poll PHY for status changes */
|
|
- schedule_delayed_work(&skge->link_thread, LINK_HZ);
|
|
|
|
|
|
+ mod_timer(&skge->link_timer, jiffies + LINK_HZ);
|
|
}
|
|
}
|
|
|
|
|
|
static void xm_check_link(struct net_device *dev)
|
|
static void xm_check_link(struct net_device *dev)
|
|
@@ -1391,10 +1392,9 @@ static void xm_check_link(struct net_device *dev)
|
|
* Since internal PHY is wired to a level triggered pin, can't
|
|
* Since internal PHY is wired to a level triggered pin, can't
|
|
* get an interrupt when carrier is detected.
|
|
* get an interrupt when carrier is detected.
|
|
*/
|
|
*/
|
|
-static void xm_link_timer(struct work_struct *work)
|
|
|
|
|
|
+static void xm_link_timer(unsigned long arg)
|
|
{
|
|
{
|
|
- struct skge_port *skge =
|
|
|
|
- container_of(work, struct skge_port, link_thread.work);
|
|
|
|
|
|
+ struct skge_port *skge = (struct skge_port *) arg;
|
|
struct net_device *dev = skge->netdev;
|
|
struct net_device *dev = skge->netdev;
|
|
struct skge_hw *hw = skge->hw;
|
|
struct skge_hw *hw = skge->hw;
|
|
int port = skge->port;
|
|
int port = skge->port;
|
|
@@ -1414,13 +1414,13 @@ static void xm_link_timer(struct work_struct *work)
|
|
goto nochange;
|
|
goto nochange;
|
|
}
|
|
}
|
|
|
|
|
|
- mutex_lock(&hw->phy_mutex);
|
|
|
|
|
|
+ spin_lock(&hw->phy_lock);
|
|
xm_check_link(dev);
|
|
xm_check_link(dev);
|
|
- mutex_unlock(&hw->phy_mutex);
|
|
|
|
|
|
+ spin_unlock(&hw->phy_lock);
|
|
|
|
|
|
nochange:
|
|
nochange:
|
|
if (netif_running(dev))
|
|
if (netif_running(dev))
|
|
- schedule_delayed_work(&skge->link_thread, LINK_HZ);
|
|
|
|
|
|
+ mod_timer(&skge->link_timer, jiffies + LINK_HZ);
|
|
}
|
|
}
|
|
|
|
|
|
static void genesis_mac_init(struct skge_hw *hw, int port)
|
|
static void genesis_mac_init(struct skge_hw *hw, int port)
|
|
@@ -2323,7 +2323,7 @@ static void skge_phy_reset(struct skge_port *skge)
|
|
netif_stop_queue(skge->netdev);
|
|
netif_stop_queue(skge->netdev);
|
|
netif_carrier_off(skge->netdev);
|
|
netif_carrier_off(skge->netdev);
|
|
|
|
|
|
- mutex_lock(&hw->phy_mutex);
|
|
|
|
|
|
+ spin_lock_bh(&hw->phy_lock);
|
|
if (hw->chip_id == CHIP_ID_GENESIS) {
|
|
if (hw->chip_id == CHIP_ID_GENESIS) {
|
|
genesis_reset(hw, port);
|
|
genesis_reset(hw, port);
|
|
genesis_mac_init(hw, port);
|
|
genesis_mac_init(hw, port);
|
|
@@ -2331,7 +2331,7 @@ static void skge_phy_reset(struct skge_port *skge)
|
|
yukon_reset(hw, port);
|
|
yukon_reset(hw, port);
|
|
yukon_init(hw, port);
|
|
yukon_init(hw, port);
|
|
}
|
|
}
|
|
- mutex_unlock(&hw->phy_mutex);
|
|
|
|
|
|
+ spin_unlock_bh(&hw->phy_lock);
|
|
|
|
|
|
dev->set_multicast_list(dev);
|
|
dev->set_multicast_list(dev);
|
|
}
|
|
}
|
|
@@ -2354,12 +2354,12 @@ static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
|
/* fallthru */
|
|
/* fallthru */
|
|
case SIOCGMIIREG: {
|
|
case SIOCGMIIREG: {
|
|
u16 val = 0;
|
|
u16 val = 0;
|
|
- mutex_lock(&hw->phy_mutex);
|
|
|
|
|
|
+ spin_lock_bh(&hw->phy_lock);
|
|
if (hw->chip_id == CHIP_ID_GENESIS)
|
|
if (hw->chip_id == CHIP_ID_GENESIS)
|
|
err = __xm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val);
|
|
err = __xm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val);
|
|
else
|
|
else
|
|
err = __gm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val);
|
|
err = __gm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val);
|
|
- mutex_unlock(&hw->phy_mutex);
|
|
|
|
|
|
+ spin_unlock_bh(&hw->phy_lock);
|
|
data->val_out = val;
|
|
data->val_out = val;
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
@@ -2368,14 +2368,14 @@ static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
|
if (!capable(CAP_NET_ADMIN))
|
|
if (!capable(CAP_NET_ADMIN))
|
|
return -EPERM;
|
|
return -EPERM;
|
|
|
|
|
|
- mutex_lock(&hw->phy_mutex);
|
|
|
|
|
|
+ spin_lock_bh(&hw->phy_lock);
|
|
if (hw->chip_id == CHIP_ID_GENESIS)
|
|
if (hw->chip_id == CHIP_ID_GENESIS)
|
|
err = xm_phy_write(hw, skge->port, data->reg_num & 0x1f,
|
|
err = xm_phy_write(hw, skge->port, data->reg_num & 0x1f,
|
|
data->val_in);
|
|
data->val_in);
|
|
else
|
|
else
|
|
err = gm_phy_write(hw, skge->port, data->reg_num & 0x1f,
|
|
err = gm_phy_write(hw, skge->port, data->reg_num & 0x1f,
|
|
data->val_in);
|
|
data->val_in);
|
|
- mutex_unlock(&hw->phy_mutex);
|
|
|
|
|
|
+ spin_unlock_bh(&hw->phy_lock);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
return err;
|
|
return err;
|
|
@@ -2481,12 +2481,12 @@ static int skge_up(struct net_device *dev)
|
|
goto free_rx_ring;
|
|
goto free_rx_ring;
|
|
|
|
|
|
/* Initialize MAC */
|
|
/* Initialize MAC */
|
|
- mutex_lock(&hw->phy_mutex);
|
|
|
|
|
|
+ spin_lock_bh(&hw->phy_lock);
|
|
if (hw->chip_id == CHIP_ID_GENESIS)
|
|
if (hw->chip_id == CHIP_ID_GENESIS)
|
|
genesis_mac_init(hw, port);
|
|
genesis_mac_init(hw, port);
|
|
else
|
|
else
|
|
yukon_mac_init(hw, port);
|
|
yukon_mac_init(hw, port);
|
|
- mutex_unlock(&hw->phy_mutex);
|
|
|
|
|
|
+ spin_unlock_bh(&hw->phy_lock);
|
|
|
|
|
|
/* Configure RAMbuffers */
|
|
/* Configure RAMbuffers */
|
|
chunk = hw->ram_size / ((hw->ports + 1)*2);
|
|
chunk = hw->ram_size / ((hw->ports + 1)*2);
|
|
@@ -2504,6 +2504,11 @@ static int skge_up(struct net_device *dev)
|
|
skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F);
|
|
skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F);
|
|
skge_led(skge, LED_MODE_ON);
|
|
skge_led(skge, LED_MODE_ON);
|
|
|
|
|
|
|
|
+ spin_lock_irq(&hw->hw_lock);
|
|
|
|
+ hw->intr_mask |= portmask[port];
|
|
|
|
+ skge_write32(hw, B0_IMSK, hw->intr_mask);
|
|
|
|
+ spin_unlock_irq(&hw->hw_lock);
|
|
|
|
+
|
|
netif_poll_enable(dev);
|
|
netif_poll_enable(dev);
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
@@ -2531,7 +2536,14 @@ static int skge_down(struct net_device *dev)
|
|
|
|
|
|
netif_stop_queue(dev);
|
|
netif_stop_queue(dev);
|
|
if (hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC)
|
|
if (hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC)
|
|
- cancel_delayed_work(&skge->link_thread);
|
|
|
|
|
|
+ del_timer_sync(&skge->link_timer);
|
|
|
|
+
|
|
|
|
+ netif_poll_disable(dev);
|
|
|
|
+
|
|
|
|
+ spin_lock_irq(&hw->hw_lock);
|
|
|
|
+ hw->intr_mask &= ~portmask[port];
|
|
|
|
+ skge_write32(hw, B0_IMSK, hw->intr_mask);
|
|
|
|
+ spin_unlock_irq(&hw->hw_lock);
|
|
|
|
|
|
skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF);
|
|
skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF);
|
|
if (hw->chip_id == CHIP_ID_GENESIS)
|
|
if (hw->chip_id == CHIP_ID_GENESIS)
|
|
@@ -2575,8 +2587,10 @@ static int skge_down(struct net_device *dev)
|
|
|
|
|
|
skge_led(skge, LED_MODE_OFF);
|
|
skge_led(skge, LED_MODE_OFF);
|
|
|
|
|
|
- netif_poll_disable(dev);
|
|
|
|
|
|
+ netif_tx_lock_bh(dev);
|
|
skge_tx_clean(dev);
|
|
skge_tx_clean(dev);
|
|
|
|
+ netif_tx_unlock_bh(dev);
|
|
|
|
+
|
|
skge_rx_clean(skge);
|
|
skge_rx_clean(skge);
|
|
|
|
|
|
kfree(skge->rx_ring.start);
|
|
kfree(skge->rx_ring.start);
|
|
@@ -2721,7 +2735,6 @@ static void skge_tx_clean(struct net_device *dev)
|
|
struct skge_port *skge = netdev_priv(dev);
|
|
struct skge_port *skge = netdev_priv(dev);
|
|
struct skge_element *e;
|
|
struct skge_element *e;
|
|
|
|
|
|
- netif_tx_lock_bh(dev);
|
|
|
|
for (e = skge->tx_ring.to_clean; e != skge->tx_ring.to_use; e = e->next) {
|
|
for (e = skge->tx_ring.to_clean; e != skge->tx_ring.to_use; e = e->next) {
|
|
struct skge_tx_desc *td = e->desc;
|
|
struct skge_tx_desc *td = e->desc;
|
|
skge_tx_free(skge, e, td->control);
|
|
skge_tx_free(skge, e, td->control);
|
|
@@ -2730,7 +2743,6 @@ static void skge_tx_clean(struct net_device *dev)
|
|
|
|
|
|
skge->tx_ring.to_clean = e;
|
|
skge->tx_ring.to_clean = e;
|
|
netif_wake_queue(dev);
|
|
netif_wake_queue(dev);
|
|
- netif_tx_unlock_bh(dev);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
static void skge_tx_timeout(struct net_device *dev)
|
|
static void skge_tx_timeout(struct net_device *dev)
|
|
@@ -3049,7 +3061,7 @@ static int skge_poll(struct net_device *dev, int *budget)
|
|
|
|
|
|
spin_lock_irqsave(&hw->hw_lock, flags);
|
|
spin_lock_irqsave(&hw->hw_lock, flags);
|
|
__netif_rx_complete(dev);
|
|
__netif_rx_complete(dev);
|
|
- hw->intr_mask |= irqmask[skge->port];
|
|
|
|
|
|
+ hw->intr_mask |= napimask[skge->port];
|
|
skge_write32(hw, B0_IMSK, hw->intr_mask);
|
|
skge_write32(hw, B0_IMSK, hw->intr_mask);
|
|
skge_read32(hw, B0_IMSK);
|
|
skge_read32(hw, B0_IMSK);
|
|
spin_unlock_irqrestore(&hw->hw_lock, flags);
|
|
spin_unlock_irqrestore(&hw->hw_lock, flags);
|
|
@@ -3160,28 +3172,29 @@ static void skge_error_irq(struct skge_hw *hw)
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
- * Interrupt from PHY are handled in work queue
|
|
|
|
|
|
+ * Interrupt from PHY are handled in tasklet (softirq)
|
|
* because accessing phy registers requires spin wait which might
|
|
* because accessing phy registers requires spin wait which might
|
|
* cause excess interrupt latency.
|
|
* cause excess interrupt latency.
|
|
*/
|
|
*/
|
|
-static void skge_extirq(struct work_struct *work)
|
|
|
|
|
|
+static void skge_extirq(unsigned long arg)
|
|
{
|
|
{
|
|
- struct skge_hw *hw = container_of(work, struct skge_hw, phy_work);
|
|
|
|
|
|
+ struct skge_hw *hw = (struct skge_hw *) arg;
|
|
int port;
|
|
int port;
|
|
|
|
|
|
- mutex_lock(&hw->phy_mutex);
|
|
|
|
for (port = 0; port < hw->ports; port++) {
|
|
for (port = 0; port < hw->ports; port++) {
|
|
struct net_device *dev = hw->dev[port];
|
|
struct net_device *dev = hw->dev[port];
|
|
- struct skge_port *skge = netdev_priv(dev);
|
|
|
|
|
|
|
|
if (netif_running(dev)) {
|
|
if (netif_running(dev)) {
|
|
|
|
+ struct skge_port *skge = netdev_priv(dev);
|
|
|
|
+
|
|
|
|
+ spin_lock(&hw->phy_lock);
|
|
if (hw->chip_id != CHIP_ID_GENESIS)
|
|
if (hw->chip_id != CHIP_ID_GENESIS)
|
|
yukon_phy_intr(skge);
|
|
yukon_phy_intr(skge);
|
|
else if (hw->phy_type == SK_PHY_BCOM)
|
|
else if (hw->phy_type == SK_PHY_BCOM)
|
|
bcom_phy_intr(skge);
|
|
bcom_phy_intr(skge);
|
|
|
|
+ spin_unlock(&hw->phy_lock);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- mutex_unlock(&hw->phy_mutex);
|
|
|
|
|
|
|
|
spin_lock_irq(&hw->hw_lock);
|
|
spin_lock_irq(&hw->hw_lock);
|
|
hw->intr_mask |= IS_EXT_REG;
|
|
hw->intr_mask |= IS_EXT_REG;
|
|
@@ -3206,7 +3219,7 @@ static irqreturn_t skge_intr(int irq, void *dev_id)
|
|
status &= hw->intr_mask;
|
|
status &= hw->intr_mask;
|
|
if (status & IS_EXT_REG) {
|
|
if (status & IS_EXT_REG) {
|
|
hw->intr_mask &= ~IS_EXT_REG;
|
|
hw->intr_mask &= ~IS_EXT_REG;
|
|
- schedule_work(&hw->phy_work);
|
|
|
|
|
|
+ tasklet_schedule(&hw->phy_task);
|
|
}
|
|
}
|
|
|
|
|
|
if (status & (IS_XA1_F|IS_R1_F)) {
|
|
if (status & (IS_XA1_F|IS_R1_F)) {
|
|
@@ -3282,23 +3295,28 @@ static int skge_set_mac_address(struct net_device *dev, void *p)
|
|
|
|
|
|
memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
|
|
memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
|
|
|
|
|
|
- /* disable Rx */
|
|
|
|
- ctrl = gma_read16(hw, port, GM_GP_CTRL);
|
|
|
|
- gma_write16(hw, port, GM_GP_CTRL, ctrl & ~GM_GPCR_RX_ENA);
|
|
|
|
|
|
+ if (!netif_running(dev)) {
|
|
|
|
+ memcpy_toio(hw->regs + B2_MAC_1 + port*8, dev->dev_addr, ETH_ALEN);
|
|
|
|
+ memcpy_toio(hw->regs + B2_MAC_2 + port*8, dev->dev_addr, ETH_ALEN);
|
|
|
|
+ } else {
|
|
|
|
+ /* disable Rx */
|
|
|
|
+ spin_lock_bh(&hw->phy_lock);
|
|
|
|
+ ctrl = gma_read16(hw, port, GM_GP_CTRL);
|
|
|
|
+ gma_write16(hw, port, GM_GP_CTRL, ctrl & ~GM_GPCR_RX_ENA);
|
|
|
|
|
|
- memcpy_toio(hw->regs + B2_MAC_1 + port*8, dev->dev_addr, ETH_ALEN);
|
|
|
|
- memcpy_toio(hw->regs + B2_MAC_2 + port*8, dev->dev_addr, ETH_ALEN);
|
|
|
|
|
|
+ memcpy_toio(hw->regs + B2_MAC_1 + port*8, dev->dev_addr, ETH_ALEN);
|
|
|
|
+ memcpy_toio(hw->regs + B2_MAC_2 + port*8, dev->dev_addr, ETH_ALEN);
|
|
|
|
|
|
- if (netif_running(dev)) {
|
|
|
|
if (hw->chip_id == CHIP_ID_GENESIS)
|
|
if (hw->chip_id == CHIP_ID_GENESIS)
|
|
xm_outaddr(hw, port, XM_SA, dev->dev_addr);
|
|
xm_outaddr(hw, port, XM_SA, dev->dev_addr);
|
|
else {
|
|
else {
|
|
gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr);
|
|
gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr);
|
|
gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr);
|
|
gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr);
|
|
}
|
|
}
|
|
- }
|
|
|
|
|
|
|
|
- gma_write16(hw, port, GM_GP_CTRL, ctrl);
|
|
|
|
|
|
+ gma_write16(hw, port, GM_GP_CTRL, ctrl);
|
|
|
|
+ spin_unlock_bh(&hw->phy_lock);
|
|
|
|
+ }
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -3413,10 +3431,9 @@ static int skge_reset(struct skge_hw *hw)
|
|
else
|
|
else
|
|
hw->ram_size = t8 * 4096;
|
|
hw->ram_size = t8 * 4096;
|
|
|
|
|
|
- hw->intr_mask = IS_HW_ERR | IS_PORT_1;
|
|
|
|
- if (hw->ports > 1)
|
|
|
|
- hw->intr_mask |= IS_PORT_2;
|
|
|
|
|
|
+ hw->intr_mask = IS_HW_ERR;
|
|
|
|
|
|
|
|
+ /* Use PHY IRQ for all but fiber based Genesis board */
|
|
if (!(hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC))
|
|
if (!(hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC))
|
|
hw->intr_mask |= IS_EXT_REG;
|
|
hw->intr_mask |= IS_EXT_REG;
|
|
|
|
|
|
@@ -3484,14 +3501,12 @@ static int skge_reset(struct skge_hw *hw)
|
|
|
|
|
|
skge_write32(hw, B0_IMSK, hw->intr_mask);
|
|
skge_write32(hw, B0_IMSK, hw->intr_mask);
|
|
|
|
|
|
- mutex_lock(&hw->phy_mutex);
|
|
|
|
for (i = 0; i < hw->ports; i++) {
|
|
for (i = 0; i < hw->ports; i++) {
|
|
if (hw->chip_id == CHIP_ID_GENESIS)
|
|
if (hw->chip_id == CHIP_ID_GENESIS)
|
|
genesis_reset(hw, i);
|
|
genesis_reset(hw, i);
|
|
else
|
|
else
|
|
yukon_reset(hw, i);
|
|
yukon_reset(hw, i);
|
|
}
|
|
}
|
|
- mutex_unlock(&hw->phy_mutex);
|
|
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -3539,6 +3554,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
|
|
skge->netdev = dev;
|
|
skge->netdev = dev;
|
|
skge->hw = hw;
|
|
skge->hw = hw;
|
|
skge->msg_enable = netif_msg_init(debug, default_msg);
|
|
skge->msg_enable = netif_msg_init(debug, default_msg);
|
|
|
|
+
|
|
skge->tx_ring.count = DEFAULT_TX_RING_SIZE;
|
|
skge->tx_ring.count = DEFAULT_TX_RING_SIZE;
|
|
skge->rx_ring.count = DEFAULT_RX_RING_SIZE;
|
|
skge->rx_ring.count = DEFAULT_RX_RING_SIZE;
|
|
|
|
|
|
@@ -3555,7 +3571,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
|
|
skge->port = port;
|
|
skge->port = port;
|
|
|
|
|
|
/* Only used for Genesis XMAC */
|
|
/* Only used for Genesis XMAC */
|
|
- INIT_DELAYED_WORK(&skge->link_thread, xm_link_timer);
|
|
|
|
|
|
+ setup_timer(&skge->link_timer, xm_link_timer, (unsigned long) skge);
|
|
|
|
|
|
if (hw->chip_id != CHIP_ID_GENESIS) {
|
|
if (hw->chip_id != CHIP_ID_GENESIS) {
|
|
dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
|
|
dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
|
|
@@ -3637,9 +3653,9 @@ static int __devinit skge_probe(struct pci_dev *pdev,
|
|
}
|
|
}
|
|
|
|
|
|
hw->pdev = pdev;
|
|
hw->pdev = pdev;
|
|
- mutex_init(&hw->phy_mutex);
|
|
|
|
- INIT_WORK(&hw->phy_work, skge_extirq);
|
|
|
|
spin_lock_init(&hw->hw_lock);
|
|
spin_lock_init(&hw->hw_lock);
|
|
|
|
+ spin_lock_init(&hw->phy_lock);
|
|
|
|
+ tasklet_init(&hw->phy_task, &skge_extirq, (unsigned long) hw);
|
|
|
|
|
|
hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000);
|
|
hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000);
|
|
if (!hw->regs) {
|
|
if (!hw->regs) {
|
|
@@ -3725,6 +3741,8 @@ static void __devexit skge_remove(struct pci_dev *pdev)
|
|
dev0 = hw->dev[0];
|
|
dev0 = hw->dev[0];
|
|
unregister_netdev(dev0);
|
|
unregister_netdev(dev0);
|
|
|
|
|
|
|
|
+ tasklet_disable(&hw->phy_task);
|
|
|
|
+
|
|
spin_lock_irq(&hw->hw_lock);
|
|
spin_lock_irq(&hw->hw_lock);
|
|
hw->intr_mask = 0;
|
|
hw->intr_mask = 0;
|
|
skge_write32(hw, B0_IMSK, 0);
|
|
skge_write32(hw, B0_IMSK, 0);
|