Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/shaggy...
[pandora-kernel.git] / drivers / net / s2io.c
index b8c0e7b..f2ba944 100644 (file)
@@ -84,7 +84,7 @@
 #include "s2io.h"
 #include "s2io-regs.h"
 
-#define DRV_VERSION "2.0.26.5"
+#define DRV_VERSION "2.0.26.17"
 
 /* S2io Driver name & version. */
 static char s2io_driver_name[] = "Neterion";
@@ -1081,7 +1081,7 @@ static int init_nic(struct s2io_nic *nic)
        /* to set the swapper controle on the card */
        if(s2io_set_swapper(nic)) {
                DBG_PRINT(ERR_DBG,"ERROR: Setting Swapper failed\n");
-               return -1;
+               return -EIO;
        }
 
        /*
@@ -1100,6 +1100,20 @@ static int init_nic(struct s2io_nic *nic)
        msleep(500);
        val64 = readq(&bar0->sw_reset);
 
+       /* Ensure that it's safe to access registers by checking
+        * RIC_RUNNING bit is reset. Check is valid only for XframeII.
+        */
+       if (nic->device_type == XFRAME_II_DEVICE) {
+               for (i = 0; i < 50; i++) {
+                       val64 = readq(&bar0->adapter_status);
+                       if (!(val64 & ADAPTER_STATUS_RIC_RUNNING))
+                               break;
+                       msleep(10);
+               }
+               if (i == 50)
+                       return -ENODEV;
+       }
+
        /*  Enable Receiving broadcasts */
        add = &bar0->mac_cfg;
        val64 = readq(&bar0->mac_cfg);
@@ -1503,7 +1517,7 @@ static int init_nic(struct s2io_nic *nic)
                        DBG_PRINT(ERR_DBG, "%s: failed rts ds steering",
                                dev->name);
                        DBG_PRINT(ERR_DBG, "set on codepoint %d\n", i);
-                       return FAILURE;
+                       return -ENODEV;
                }
        }
 
@@ -1570,7 +1584,7 @@ static int init_nic(struct s2io_nic *nic)
                if (time > 10) {
                        DBG_PRINT(ERR_DBG, "%s: TTI init Failed\n",
                                  dev->name);
-                       return -1;
+                       return -ENODEV;
                }
                msleep(50);
                time++;
@@ -1623,7 +1637,7 @@ static int init_nic(struct s2io_nic *nic)
                        if (time > 10) {
                                DBG_PRINT(ERR_DBG, "%s: RTI init Failed\n",
                                          dev->name);
-                               return -1;
+                               return -ENODEV;
                        }
                        time++;
                        msleep(50);
@@ -2690,9 +2704,6 @@ static int s2io_poll(struct napi_struct *napi, int budget)
        struct XENA_dev_config __iomem *bar0 = nic->bar0;
        int i;
 
-       if (!is_s2io_card_up(nic))
-               return 0;
-
        mac_control = &nic->mac_control;
        config = &nic->config;
 
@@ -3723,7 +3734,7 @@ static int s2io_enable_msi_x(struct s2io_nic *nic)
 }
 
 /* Handle software interrupt used during MSI(X) test */
-static irqreturn_t __devinit s2io_test_intr(int irq, void *dev_id)
+static irqreturn_t s2io_test_intr(int irq, void *dev_id)
 {
        struct s2io_nic *sp = dev_id;
 
@@ -3734,7 +3745,7 @@ static irqreturn_t __devinit s2io_test_intr(int irq, void *dev_id)
 }
 
 /* Test interrupt path by forcing a a software IRQ */
-static int __devinit s2io_test_msi(struct s2io_nic *sp)
+static int s2io_test_msi(struct s2io_nic *sp)
 {
        struct pci_dev *pdev = sp->pdev;
        struct XENA_dev_config __iomem *bar0 = sp->bar0;
@@ -3775,6 +3786,40 @@ static int __devinit s2io_test_msi(struct s2io_nic *sp)
 
        return err;
 }
+
+static void remove_msix_isr(struct s2io_nic *sp)
+{
+       int i;
+       u16 msi_control;
+
+       for (i = 0; i < MAX_REQUESTED_MSI_X; i++) {
+               if (sp->s2io_entries[i].in_use ==
+                       MSIX_REGISTERED_SUCCESS) {
+                       int vector = sp->entries[i].vector;
+                       void *arg = sp->s2io_entries[i].arg;
+                       free_irq(vector, arg);
+               }
+       }
+
+       kfree(sp->entries);
+       kfree(sp->s2io_entries);
+       sp->entries = NULL;
+       sp->s2io_entries = NULL;
+
+       pci_read_config_word(sp->pdev, 0x42, &msi_control);
+       msi_control &= 0xFFFE; /* Disable MSI */
+       pci_write_config_word(sp->pdev, 0x42, msi_control);
+
+       pci_disable_msix(sp->pdev);
+}
+
+static void remove_inta_isr(struct s2io_nic *sp)
+{
+       struct net_device *dev = sp->dev;
+
+       free_irq(sp->pdev->irq, dev);
+}
+
 /* ********************************************************* *
  * Functions defined below concern the OS part of the driver *
  * ********************************************************* */
@@ -3803,34 +3848,13 @@ static int s2io_open(struct net_device *dev)
        netif_carrier_off(dev);
        sp->last_link_state = 0;
 
-       napi_enable(&sp->napi);
-
        if (sp->config.intr_type == MSI_X) {
                int ret = s2io_enable_msi_x(sp);
 
                if (!ret) {
-                       u16 msi_control;
-
                        ret = s2io_test_msi(sp);
-
                        /* rollback MSI-X, will re-enable during add_isr() */
-                       kfree(sp->entries);
-                       sp->mac_control.stats_info->sw_stat.mem_freed +=
-                               (MAX_REQUESTED_MSI_X *
-                               sizeof(struct msix_entry));
-                       kfree(sp->s2io_entries);
-                       sp->mac_control.stats_info->sw_stat.mem_freed +=
-                               (MAX_REQUESTED_MSI_X *
-                               sizeof(struct s2io_msix_entry));
-                       sp->entries = NULL;
-                       sp->s2io_entries = NULL;
-
-                       pci_read_config_word(sp->pdev, 0x42, &msi_control);
-                       msi_control &= 0xFFFE; /* Disable MSI */
-                       pci_write_config_word(sp->pdev, 0x42, msi_control);
-
-                       pci_disable_msix(sp->pdev);
-
+                       remove_msix_isr(sp);
                }
                if (ret) {
 
@@ -3866,7 +3890,6 @@ static int s2io_open(struct net_device *dev)
        return 0;
 
 hw_init_failed:
-       napi_disable(&sp->napi);
        if (sp->config.intr_type == MSI_X) {
                if (sp->entries) {
                        kfree(sp->entries);
@@ -3899,8 +3922,13 @@ static int s2io_close(struct net_device *dev)
 {
        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);
-       napi_disable(&sp->napi);
        /* Reset card, kill tasklet and free Tx and Rx buffers. */
        s2io_card_down(sp);
 
@@ -6340,6 +6368,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)
 {
        struct s2io_nic *sp = dev->priv;
+       int ret = 0;
 
        if ((new_mtu < MIN_MTU) || (new_mtu > S2IO_JUMBO_SIZE)) {
                DBG_PRINT(ERR_DBG, "%s: MTU size is invalid.\n",
@@ -6351,9 +6380,11 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu)
        if (netif_running(dev)) {
                s2io_card_down(sp);
                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",
                                  __FUNCTION__);
+                       return ret;
                }
                if (netif_queue_stopped(dev))
                        netif_wake_queue(dev);
@@ -6364,7 +6395,7 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu)
                writeq(vBIT(val64, 2, 14), &bar0->rmac_max_pyld_len);
        }
 
-       return 0;
+       return ret;
 }
 
 /**
@@ -6719,15 +6750,22 @@ static int s2io_add_isr(struct s2io_nic * sp)
                                }
                        }
                        if (err) {
+                               remove_msix_isr(sp);
                                DBG_PRINT(ERR_DBG,"%s:MSI-X-%d registration "
                                          "failed\n", dev->name, i);
-                               DBG_PRINT(ERR_DBG, "Returned: %d\n", err);
-                               return -1;
+                               DBG_PRINT(ERR_DBG, "%s: defaulting to INTA\n",
+                                                dev->name);
+                               sp->config.intr_type = INTA;
+                               break;
                        }
                        sp->s2io_entries[i].in_use = MSIX_REGISTERED_SUCCESS;
                }
-               printk("MSI-X-TX %d entries enabled\n",msix_tx_cnt);
-               printk("MSI-X-RX %d entries enabled\n",msix_rx_cnt);
+               if (!err) {
+                       printk(KERN_INFO "MSI-X-TX %d entries enabled\n",
+                               msix_tx_cnt);
+                       printk(KERN_INFO "MSI-X-RX %d entries enabled\n",
+                               msix_rx_cnt);
+               }
        }
        if (sp->config.intr_type == INTA) {
                err = request_irq((int) sp->pdev->irq, s2io_isr, IRQF_SHARED,
@@ -6742,40 +6780,10 @@ static int s2io_add_isr(struct s2io_nic * sp)
 }
 static void s2io_rem_isr(struct s2io_nic * sp)
 {
-       struct net_device *dev = sp->dev;
-       struct swStat *stats = &sp->mac_control.stats_info->sw_stat;
-
-       if (sp->config.intr_type == MSI_X) {
-               int i;
-               u16 msi_control;
-
-               for (i=1; (sp->s2io_entries[i].in_use ==
-                       MSIX_REGISTERED_SUCCESS); i++) {
-                       int vector = sp->entries[i].vector;
-                       void *arg = sp->s2io_entries[i].arg;
-
-                       synchronize_irq(vector);
-                       free_irq(vector, arg);
-               }
-
-               kfree(sp->entries);
-               stats->mem_freed +=
-                       (MAX_REQUESTED_MSI_X * sizeof(struct msix_entry));
-               kfree(sp->s2io_entries);
-               stats->mem_freed +=
-                       (MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry));
-               sp->entries = NULL;
-               sp->s2io_entries = NULL;
-
-               pci_read_config_word(sp->pdev, 0x42, &msi_control);
-               msi_control &= 0xFFFE; /* Disable MSI */
-               pci_write_config_word(sp->pdev, 0x42, msi_control);
-
-               pci_disable_msix(sp->pdev);
-       } else {
-               synchronize_irq(sp->pdev->irq);
-               free_irq(sp->pdev->irq, dev);
-       }
+       if (sp->config.intr_type == MSI_X)
+               remove_msix_isr(sp);
+       else
+               remove_inta_isr(sp);
 }
 
 static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
@@ -6784,6 +6792,11 @@ static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
        struct XENA_dev_config __iomem *bar0 = sp->bar0;
        unsigned long flags;
        register u64 val64 = 0;
+       struct config_param *config;
+       config = &sp->config;
+
+       if (!is_s2io_card_up(sp))
+               return;
 
        del_timer_sync(&sp->alarm_timer);
        /* If s2io_set_link task is executing, wait till it completes. */
@@ -6792,6 +6805,10 @@ static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
        }
        clear_bit(__S2IO_STATE_CARD_UP, &sp->state);
 
+       /* Disable napi */
+       if (config->napi)
+               napi_disable(&sp->napi);
+
        /* disable Tx and Rx traffic on the NIC */
        if (do_io)
                stop_nic(sp);
@@ -6858,11 +6875,13 @@ static int s2io_card_up(struct s2io_nic * sp)
        u16 interruptible;
 
        /* 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",
                          dev->name);
-               s2io_reset(sp);
-               return -ENODEV;
+               if (ret != -EIO)
+                       s2io_reset(sp);
+               return ret;
        }
 
        /*
@@ -6883,6 +6902,11 @@ static int s2io_card_up(struct s2io_nic * sp)
                DBG_PRINT(INFO_DBG, "Buf in ring:%d is %d:\n", i,
                          atomic_read(&sp->rx_bufs_left[i]));
        }
+
+       /* Initialise napi */
+       if (config->napi)
+               napi_enable(&sp->napi);
+
        /* Maintain the state prior to the open */
        if (sp->promisc_flg)
                sp->promisc_flg = 0;