|
@@ -68,8 +68,8 @@
|
|
|
|
|
|
#define DRV_MODULE_NAME "tg3"
|
|
|
#define PFX DRV_MODULE_NAME ": "
|
|
|
-#define DRV_MODULE_VERSION "3.62"
|
|
|
-#define DRV_MODULE_RELDATE "June 30, 2006"
|
|
|
+#define DRV_MODULE_VERSION "3.63"
|
|
|
+#define DRV_MODULE_RELDATE "July 25, 2006"
|
|
|
|
|
|
#define TG3_DEF_MAC_MODE 0
|
|
|
#define TG3_DEF_RX_MODE 0
|
|
@@ -3590,6 +3590,28 @@ static irqreturn_t tg3_test_isr(int irq, void *dev_id,
|
|
|
static int tg3_init_hw(struct tg3 *, int);
|
|
|
static int tg3_halt(struct tg3 *, int, int);
|
|
|
|
|
|
+/* Restart hardware after configuration changes, self-test, etc.
|
|
|
+ * Invoked with tp->lock held.
|
|
|
+ */
|
|
|
+static int tg3_restart_hw(struct tg3 *tp, int reset_phy)
|
|
|
+{
|
|
|
+ int err;
|
|
|
+
|
|
|
+ err = tg3_init_hw(tp, reset_phy);
|
|
|
+ if (err) {
|
|
|
+ printk(KERN_ERR PFX "%s: Failed to re-initialize device, "
|
|
|
+ "aborting.\n", tp->dev->name);
|
|
|
+ tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
|
|
|
+ tg3_full_unlock(tp);
|
|
|
+ del_timer_sync(&tp->timer);
|
|
|
+ tp->irq_sync = 0;
|
|
|
+ netif_poll_enable(tp->dev);
|
|
|
+ dev_close(tp->dev);
|
|
|
+ tg3_full_lock(tp, 0);
|
|
|
+ }
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
#ifdef CONFIG_NET_POLL_CONTROLLER
|
|
|
static void tg3_poll_controller(struct net_device *dev)
|
|
|
{
|
|
@@ -3630,13 +3652,15 @@ static void tg3_reset_task(void *_data)
|
|
|
}
|
|
|
|
|
|
tg3_halt(tp, RESET_KIND_SHUTDOWN, 0);
|
|
|
- tg3_init_hw(tp, 1);
|
|
|
+ if (tg3_init_hw(tp, 1))
|
|
|
+ goto out;
|
|
|
|
|
|
tg3_netif_start(tp);
|
|
|
|
|
|
if (restart_timer)
|
|
|
mod_timer(&tp->timer, jiffies + 1);
|
|
|
|
|
|
+out:
|
|
|
tp->tg3_flags &= ~TG3_FLAG_IN_RESET_TASK;
|
|
|
|
|
|
tg3_full_unlock(tp);
|
|
@@ -4124,6 +4148,7 @@ static inline void tg3_set_mtu(struct net_device *dev, struct tg3 *tp,
|
|
|
static int tg3_change_mtu(struct net_device *dev, int new_mtu)
|
|
|
{
|
|
|
struct tg3 *tp = netdev_priv(dev);
|
|
|
+ int err;
|
|
|
|
|
|
if (new_mtu < TG3_MIN_MTU || new_mtu > TG3_MAX_MTU(tp))
|
|
|
return -EINVAL;
|
|
@@ -4144,13 +4169,14 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu)
|
|
|
|
|
|
tg3_set_mtu(dev, tp, new_mtu);
|
|
|
|
|
|
- tg3_init_hw(tp, 0);
|
|
|
+ err = tg3_restart_hw(tp, 0);
|
|
|
|
|
|
- tg3_netif_start(tp);
|
|
|
+ if (!err)
|
|
|
+ tg3_netif_start(tp);
|
|
|
|
|
|
tg3_full_unlock(tp);
|
|
|
|
|
|
- return 0;
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
/* Free up pending packets in all rx/tx rings.
|
|
@@ -4232,7 +4258,7 @@ static void tg3_free_rings(struct tg3 *tp)
|
|
|
* end up in the driver. tp->{tx,}lock are held and thus
|
|
|
* we may not sleep.
|
|
|
*/
|
|
|
-static void tg3_init_rings(struct tg3 *tp)
|
|
|
+static int tg3_init_rings(struct tg3 *tp)
|
|
|
{
|
|
|
u32 i;
|
|
|
|
|
@@ -4281,18 +4307,38 @@ static void tg3_init_rings(struct tg3 *tp)
|
|
|
|
|
|
/* Now allocate fresh SKBs for each rx ring. */
|
|
|
for (i = 0; i < tp->rx_pending; i++) {
|
|
|
- if (tg3_alloc_rx_skb(tp, RXD_OPAQUE_RING_STD,
|
|
|
- -1, i) < 0)
|
|
|
+ if (tg3_alloc_rx_skb(tp, RXD_OPAQUE_RING_STD, -1, i) < 0) {
|
|
|
+ printk(KERN_WARNING PFX
|
|
|
+ "%s: Using a smaller RX standard ring, "
|
|
|
+ "only %d out of %d buffers were allocated "
|
|
|
+ "successfully.\n",
|
|
|
+ tp->dev->name, i, tp->rx_pending);
|
|
|
+ if (i == 0)
|
|
|
+ return -ENOMEM;
|
|
|
+ tp->rx_pending = i;
|
|
|
break;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
if (tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) {
|
|
|
for (i = 0; i < tp->rx_jumbo_pending; i++) {
|
|
|
if (tg3_alloc_rx_skb(tp, RXD_OPAQUE_RING_JUMBO,
|
|
|
- -1, i) < 0)
|
|
|
+ -1, i) < 0) {
|
|
|
+ printk(KERN_WARNING PFX
|
|
|
+ "%s: Using a smaller RX jumbo ring, "
|
|
|
+ "only %d out of %d buffers were "
|
|
|
+ "allocated successfully.\n",
|
|
|
+ tp->dev->name, i, tp->rx_jumbo_pending);
|
|
|
+ if (i == 0) {
|
|
|
+ tg3_free_rings(tp);
|
|
|
+ return -ENOMEM;
|
|
|
+ }
|
|
|
+ tp->rx_jumbo_pending = i;
|
|
|
break;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -5815,6 +5861,7 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p)
|
|
|
{
|
|
|
struct tg3 *tp = netdev_priv(dev);
|
|
|
struct sockaddr *addr = p;
|
|
|
+ int err = 0;
|
|
|
|
|
|
if (!is_valid_ether_addr(addr->sa_data))
|
|
|
return -EINVAL;
|
|
@@ -5832,9 +5879,9 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p)
|
|
|
tg3_full_lock(tp, 1);
|
|
|
|
|
|
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
|
|
|
- tg3_init_hw(tp, 0);
|
|
|
-
|
|
|
- tg3_netif_start(tp);
|
|
|
+ err = tg3_restart_hw(tp, 0);
|
|
|
+ if (!err)
|
|
|
+ tg3_netif_start(tp);
|
|
|
tg3_full_unlock(tp);
|
|
|
} else {
|
|
|
spin_lock_bh(&tp->lock);
|
|
@@ -5842,7 +5889,7 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p)
|
|
|
spin_unlock_bh(&tp->lock);
|
|
|
}
|
|
|
|
|
|
- return 0;
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
/* tp->lock is held. */
|
|
@@ -5942,7 +5989,9 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
|
|
|
* can only do this after the hardware has been
|
|
|
* successfully reset.
|
|
|
*/
|
|
|
- tg3_init_rings(tp);
|
|
|
+ err = tg3_init_rings(tp);
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
|
|
|
/* This value is determined during the probe time DMA
|
|
|
* engine test, tg3_test_dma.
|
|
@@ -7956,7 +8005,7 @@ static void tg3_get_ringparam(struct net_device *dev, struct ethtool_ringparam *
|
|
|
static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
|
|
|
{
|
|
|
struct tg3 *tp = netdev_priv(dev);
|
|
|
- int irq_sync = 0;
|
|
|
+ int irq_sync = 0, err = 0;
|
|
|
|
|
|
if ((ering->rx_pending > TG3_RX_RING_SIZE - 1) ||
|
|
|
(ering->rx_jumbo_pending > TG3_RX_JUMBO_RING_SIZE - 1) ||
|
|
@@ -7980,13 +8029,14 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e
|
|
|
|
|
|
if (netif_running(dev)) {
|
|
|
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
|
|
|
- tg3_init_hw(tp, 1);
|
|
|
- tg3_netif_start(tp);
|
|
|
+ err = tg3_restart_hw(tp, 1);
|
|
|
+ if (!err)
|
|
|
+ tg3_netif_start(tp);
|
|
|
}
|
|
|
|
|
|
tg3_full_unlock(tp);
|
|
|
|
|
|
- return 0;
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
static void tg3_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
|
|
@@ -8001,7 +8051,7 @@ static void tg3_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam
|
|
|
static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
|
|
|
{
|
|
|
struct tg3 *tp = netdev_priv(dev);
|
|
|
- int irq_sync = 0;
|
|
|
+ int irq_sync = 0, err = 0;
|
|
|
|
|
|
if (netif_running(dev)) {
|
|
|
tg3_netif_stop(tp);
|
|
@@ -8025,13 +8075,14 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
|
|
|
|
|
|
if (netif_running(dev)) {
|
|
|
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
|
|
|
- tg3_init_hw(tp, 1);
|
|
|
- tg3_netif_start(tp);
|
|
|
+ err = tg3_restart_hw(tp, 1);
|
|
|
+ if (!err)
|
|
|
+ tg3_netif_start(tp);
|
|
|
}
|
|
|
|
|
|
tg3_full_unlock(tp);
|
|
|
|
|
|
- return 0;
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
static u32 tg3_get_rx_csum(struct net_device *dev)
|
|
@@ -8666,7 +8717,9 @@ static int tg3_test_loopback(struct tg3 *tp)
|
|
|
if (!netif_running(tp->dev))
|
|
|
return TG3_LOOPBACK_FAILED;
|
|
|
|
|
|
- tg3_reset_hw(tp, 1);
|
|
|
+ err = tg3_reset_hw(tp, 1);
|
|
|
+ if (err)
|
|
|
+ return TG3_LOOPBACK_FAILED;
|
|
|
|
|
|
if (tg3_run_loopback(tp, TG3_MAC_LOOPBACK))
|
|
|
err |= TG3_MAC_LOOPBACK_FAILED;
|
|
@@ -8740,8 +8793,8 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
|
|
|
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
|
|
|
if (netif_running(dev)) {
|
|
|
tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE;
|
|
|
- tg3_init_hw(tp, 1);
|
|
|
- tg3_netif_start(tp);
|
|
|
+ if (!tg3_restart_hw(tp, 1))
|
|
|
+ tg3_netif_start(tp);
|
|
|
}
|
|
|
|
|
|
tg3_full_unlock(tp);
|
|
@@ -11699,7 +11752,8 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state)
|
|
|
tg3_full_lock(tp, 0);
|
|
|
|
|
|
tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE;
|
|
|
- tg3_init_hw(tp, 1);
|
|
|
+ if (tg3_restart_hw(tp, 1))
|
|
|
+ goto out;
|
|
|
|
|
|
tp->timer.expires = jiffies + tp->timer_offset;
|
|
|
add_timer(&tp->timer);
|
|
@@ -11707,6 +11761,7 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state)
|
|
|
netif_device_attach(dev);
|
|
|
tg3_netif_start(tp);
|
|
|
|
|
|
+out:
|
|
|
tg3_full_unlock(tp);
|
|
|
}
|
|
|
|
|
@@ -11733,16 +11788,19 @@ static int tg3_resume(struct pci_dev *pdev)
|
|
|
tg3_full_lock(tp, 0);
|
|
|
|
|
|
tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE;
|
|
|
- tg3_init_hw(tp, 1);
|
|
|
+ err = tg3_restart_hw(tp, 1);
|
|
|
+ if (err)
|
|
|
+ goto out;
|
|
|
|
|
|
tp->timer.expires = jiffies + tp->timer_offset;
|
|
|
add_timer(&tp->timer);
|
|
|
|
|
|
tg3_netif_start(tp);
|
|
|
|
|
|
+out:
|
|
|
tg3_full_unlock(tp);
|
|
|
|
|
|
- return 0;
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
static struct pci_driver tg3_driver = {
|