Commit 9f74ffde authored by Sreenivasa Honnur's avatar Sreenivasa Honnur Committed by Jeff Garzik

S2io: Fixed the case when the card initialization fails on mtu change

Fix the case when the card initialization fails on a mtu change and then
close is called (due to ifdown), which frees non existent rx buffers.
- Returning appropriate error codes in init_nic function.
- In s2io_close function s2io_card_down is called only when device is up.
- In s2io_change_mtu function return value of s2io_card_up function
  is checked and returned if it failed.
Signed-off-by: default avatarSurjit Reang <surjit.reang@neterion.com>
Signed-off-by: default avatarSreenivasa Honnur <sreenivasa.honnur@neterion.com>
Signed-off-by: default avatarRamkrishna Vepa <ram.vepa@neterion.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent 85b161a8
...@@ -1081,7 +1081,7 @@ static int init_nic(struct s2io_nic *nic) ...@@ -1081,7 +1081,7 @@ static int init_nic(struct s2io_nic *nic)
/* to set the swapper controle on the card */ /* to set the swapper controle on the card */
if(s2io_set_swapper(nic)) { if(s2io_set_swapper(nic)) {
DBG_PRINT(ERR_DBG,"ERROR: Setting Swapper failed\n"); DBG_PRINT(ERR_DBG,"ERROR: Setting Swapper failed\n");
return -1; return -EIO;
} }
/* /*
...@@ -1503,7 +1503,7 @@ static int init_nic(struct s2io_nic *nic) ...@@ -1503,7 +1503,7 @@ static int init_nic(struct s2io_nic *nic)
DBG_PRINT(ERR_DBG, "%s: failed rts ds steering", DBG_PRINT(ERR_DBG, "%s: failed rts ds steering",
dev->name); dev->name);
DBG_PRINT(ERR_DBG, "set on codepoint %d\n", i); DBG_PRINT(ERR_DBG, "set on codepoint %d\n", i);
return FAILURE; return -ENODEV;
} }
} }
...@@ -1570,7 +1570,7 @@ static int init_nic(struct s2io_nic *nic) ...@@ -1570,7 +1570,7 @@ static int init_nic(struct s2io_nic *nic)
if (time > 10) { if (time > 10) {
DBG_PRINT(ERR_DBG, "%s: TTI init Failed\n", DBG_PRINT(ERR_DBG, "%s: TTI init Failed\n",
dev->name); dev->name);
return -1; return -ENODEV;
} }
msleep(50); msleep(50);
time++; time++;
...@@ -1623,7 +1623,7 @@ static int init_nic(struct s2io_nic *nic) ...@@ -1623,7 +1623,7 @@ static int init_nic(struct s2io_nic *nic)
if (time > 10) { if (time > 10) {
DBG_PRINT(ERR_DBG, "%s: RTI init Failed\n", DBG_PRINT(ERR_DBG, "%s: RTI init Failed\n",
dev->name); dev->name);
return -1; return -ENODEV;
} }
time++; time++;
msleep(50); msleep(50);
...@@ -3914,6 +3914,12 @@ static int s2io_close(struct net_device *dev) ...@@ -3914,6 +3914,12 @@ static int s2io_close(struct net_device *dev)
{ {
struct s2io_nic *sp = dev->priv; struct s2io_nic *sp = dev->priv;
/* Return if the device is already closed *
* Can happen when s2io_card_up failed in change_mtu *
*/
if (!is_s2io_card_up(sp))
return 0;
netif_stop_queue(dev); netif_stop_queue(dev);
napi_disable(&sp->napi); napi_disable(&sp->napi);
/* Reset card, kill tasklet and free Tx and Rx buffers. */ /* Reset card, kill tasklet and free Tx and Rx buffers. */
...@@ -6355,6 +6361,7 @@ static int s2io_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -6355,6 +6361,7 @@ static int s2io_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
static int s2io_change_mtu(struct net_device *dev, int new_mtu) static int s2io_change_mtu(struct net_device *dev, int new_mtu)
{ {
struct s2io_nic *sp = dev->priv; struct s2io_nic *sp = dev->priv;
int ret = 0;
if ((new_mtu < MIN_MTU) || (new_mtu > S2IO_JUMBO_SIZE)) { if ((new_mtu < MIN_MTU) || (new_mtu > S2IO_JUMBO_SIZE)) {
DBG_PRINT(ERR_DBG, "%s: MTU size is invalid.\n", DBG_PRINT(ERR_DBG, "%s: MTU size is invalid.\n",
...@@ -6366,9 +6373,11 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu) ...@@ -6366,9 +6373,11 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu)
if (netif_running(dev)) { if (netif_running(dev)) {
s2io_card_down(sp); s2io_card_down(sp);
netif_stop_queue(dev); netif_stop_queue(dev);
if (s2io_card_up(sp)) { ret = s2io_card_up(sp);
if (ret) {
DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n", DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n",
__FUNCTION__); __FUNCTION__);
return ret;
} }
if (netif_queue_stopped(dev)) if (netif_queue_stopped(dev))
netif_wake_queue(dev); netif_wake_queue(dev);
...@@ -6379,7 +6388,7 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu) ...@@ -6379,7 +6388,7 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu)
writeq(vBIT(val64, 2, 14), &bar0->rmac_max_pyld_len); writeq(vBIT(val64, 2, 14), &bar0->rmac_max_pyld_len);
} }
return 0; return ret;
} }
/** /**
...@@ -6777,6 +6786,9 @@ static void do_s2io_card_down(struct s2io_nic * sp, int do_io) ...@@ -6777,6 +6786,9 @@ static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
unsigned long flags; unsigned long flags;
register u64 val64 = 0; register u64 val64 = 0;
if (!is_s2io_card_up(sp))
return;
del_timer_sync(&sp->alarm_timer); del_timer_sync(&sp->alarm_timer);
/* If s2io_set_link task is executing, wait till it completes. */ /* If s2io_set_link task is executing, wait till it completes. */
while (test_and_set_bit(__S2IO_STATE_LINK_TASK, &(sp->state))) { while (test_and_set_bit(__S2IO_STATE_LINK_TASK, &(sp->state))) {
...@@ -6850,11 +6862,13 @@ static int s2io_card_up(struct s2io_nic * sp) ...@@ -6850,11 +6862,13 @@ static int s2io_card_up(struct s2io_nic * sp)
u16 interruptible; u16 interruptible;
/* Initialize the H/W I/O registers */ /* Initialize the H/W I/O registers */
if (init_nic(sp) != 0) { ret = init_nic(sp);
if (ret != 0) {
DBG_PRINT(ERR_DBG, "%s: H/W initialization failed\n", DBG_PRINT(ERR_DBG, "%s: H/W initialization failed\n",
dev->name); dev->name);
s2io_reset(sp); if (ret != -EIO)
return -ENODEV; s2io_reset(sp);
return ret;
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment