diff -urN vanilla-linux/drivers/net/s2io.c linux-2.6.8.1/drivers/net/s2io.c --- vanilla-linux/drivers/net/s2io.c 2004-10-06 15:18:10.000000000 -0700 +++ linux-2.6.8.1/drivers/net/s2io.c 2004-10-06 16:19:52.821420504 -0700 @@ -1525,6 +1525,11 @@ blk++; } + if (!(rxdp->Control_1 & RXD_OWN_XENA)) { + memset(rxdp, 0, sizeof(RxD_t)); + continue; + } + skb = (struct sk_buff *) ((unsigned long) rxdp-> Host_Control); @@ -1887,7 +1892,7 @@ if (val64 & SERR_SOURCE_ANY) { DBG_PRINT(ERR_DBG, "%s: Device indicates ", dev->name); DBG_PRINT(ERR_DBG, "serious error!!\n"); - netif_stop_queue(dev); + schedule_work(&nic->rst_timer_task); } /* Other type of interrupts are not being handled now, TODO */ @@ -2205,6 +2210,17 @@ } tasklet_kill(&sp->task); + /* Free the Registered IRQ */ + free_irq(dev->irq, dev); + + /* Flush all scheduled tasks */ + if (sp->task_flag == 1) { + DBG_PRINT(INFO_DBG, "%s: Calling close from a task\n", + dev->name); + } else { + flush_scheduled_work(); + } + /* Check if the device is Quiescent and then Reset the NIC */ do { val64 = readq(&bar0->adapter_status); @@ -2225,9 +2241,6 @@ } while (1); s2io_reset(sp); - /* Free the Registered IRQ */ - free_irq(dev->irq, dev); - /* Free all Tx Buffers waiting for transmission */ free_tx_buffers(sp); @@ -2982,9 +2995,10 @@ */ #define S2IO_DEV_ID 5 -static u32 read_eeprom(nic_t * sp, int off) +static int read_eeprom(nic_t * sp, int off, u32 * data) { - u32 data = -1, exit_cnt = 0; + int ret = -1; + u32 exit_cnt = 0; u64 val64; XENA_dev_config_t *bar0 = (XENA_dev_config_t *) sp->bar0; @@ -2996,7 +3010,8 @@ while (exit_cnt < 5) { val64 = readq(&bar0->i2c_control); if (I2C_CONTROL_CNTL_END(val64)) { - data = I2C_CONTROL_GET_DATA(val64); + *data = I2C_CONTROL_GET_DATA(val64); + ret = 0; break; } set_current_state(TASK_UNINTERRUPTIBLE); @@ -3004,7 +3019,7 @@ exit_cnt++; } - return data; + return ret; } /** @@ -3073,8 +3088,7 @@ eeprom->len = XENA_EEPROM_SPACE - eeprom->offset; for (i = 0; i < eeprom->len; i += 4) { - data = read_eeprom(sp, eeprom->offset + i); - if (data < 0) { + if (read_eeprom(sp, (eeprom->offset + i), &data)) { DBG_PRINT(ERR_DBG, "Read of EEPROM failed\n"); return -EFAULT; } @@ -3213,7 +3227,8 @@ static int s2io_eeprom_test(nic_t * sp, uint64_t * data) { - int fail = 0, ret_data; + int fail = 0; + u32 ret_data; /* Test Write Error at offset 0 */ if (!write_eeprom(sp, 0, 0, 3)) @@ -3222,7 +3237,7 @@ /* Test Write at offset 4f0 */ if (write_eeprom(sp, 0x4F0, 0x01234567, 3)) fail = 1; - if ((ret_data = read_eeprom(sp, 0x4F0)) < 0) + if (read_eeprom(sp, 0x4F0, &ret_data)) fail = 1; if (ret_data != 0x01234567) @@ -3238,7 +3253,7 @@ /* Test Write Request at offset 0x7fc */ if (write_eeprom(sp, 0x7FC, 0x01234567, 3)) fail = 1; - if ((ret_data = read_eeprom(sp, 0x7FC)) < 0) + if (read_eeprom(sp, 0x7FC, &ret_data)) fail = 1; if (ret_data != 0x01234567) @@ -3811,7 +3826,9 @@ struct net_device *dev = (struct net_device *) data; nic_t *sp = dev->priv; + sp->task_flag = 1; s2io_close(dev); + sp->task_flag = 0; sp->device_close_flag = TRUE; s2io_open(dev); DBG_PRINT(ERR_DBG, @@ -4275,18 +4292,13 @@ INIT_WORK(&sp->set_link_task, (void (*)(void *)) s2io_set_link, sp); - if (register_netdev(dev)) { - DBG_PRINT(ERR_DBG, "Device registration failed\n"); - goto register_failed; - } - pci_save_state(sp->pdev, sp->config_space); /* Setting swapper control on the NIC, for proper reset operation */ if (s2io_set_swapper(sp)) { DBG_PRINT(ERR_DBG, "%s:swapper settings are wrong\n", dev->name); - goto register_failed; + goto set_swap_failed; } /* Fix for all "FFs" MAC address problems observed on Alpha platforms */ @@ -4363,6 +4375,11 @@ sp->rx_csum = 1; /* Rx chksum verify enabled by default */ + if (register_netdev(dev)) { + DBG_PRINT(ERR_DBG, "Device registration failed\n"); + goto register_failed; + } + /* * Make Link state as off at this point, when the Link change * interrupt comes the state will be automatically changed to @@ -4373,9 +4390,8 @@ return 0; - set_swap_failed: - unregister_netdev(dev); register_failed: + set_swap_failed: iounmap(sp->bar1); bar1_remap_failed: iounmap(sp->bar0); diff -urN vanilla-linux/drivers/net/s2io.h linux-2.6.8.1/drivers/net/s2io.h --- vanilla-linux/drivers/net/s2io.h 2004-10-06 15:15:03.000000000 -0700 +++ linux-2.6.8.1/drivers/net/s2io.h 2004-10-06 16:19:52.829419288 -0700 @@ -668,6 +668,8 @@ u16 last_link_state; #define LINK_DOWN 1 #define LINK_UP 2 + + int task_flag; } nic_t; #define RESET_ERROR 1;