cxgb3: Wait longer for control packets on initialization
[safe/jmp/linux-2.6] / drivers / net / cxgb3 / cxgb3_main.c
index c9113d3..e3f1b85 100644 (file)
@@ -44,6 +44,9 @@
 #include <linux/rtnetlink.h>
 #include <linux/firmware.h>
 #include <linux/log2.h>
+#include <linux/stringify.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
 #include <asm/uaccess.h>
 
 #include "common.h"
@@ -79,7 +82,7 @@ enum {
 #define CH_DEVICE(devid, idx) \
        { PCI_VENDOR_ID_CHELSIO, devid, PCI_ANY_ID, PCI_ANY_ID, 0, 0, idx }
 
-static const struct pci_device_id cxgb3_pci_tbl[] = {
+static DEFINE_PCI_DEVICE_TABLE(cxgb3_pci_tbl) = {
        CH_DEVICE(0x20, 0),     /* PE9000 */
        CH_DEVICE(0x21, 1),     /* T302E */
        CH_DEVICE(0x22, 2),     /* T310E */
@@ -139,7 +142,7 @@ MODULE_PARM_DESC(ofld_disable, "whether to enable offload at init time or not");
  * will block keventd as it needs the rtnl lock, and we'll deadlock waiting
  * for our work to complete.  Get our own work queue to solve this.
  */
-static struct workqueue_struct *cxgb3_wq;
+struct workqueue_struct *cxgb3_wq;
 
 /**
  *     link_report - show link status and link speed/duplex
@@ -323,11 +326,9 @@ void t3_os_phymod_changed(struct adapter *adap, int port_id)
 
 static void cxgb_set_rxmode(struct net_device *dev)
 {
-       struct t3_rx_mode rm;
        struct port_info *pi = netdev_priv(dev);
 
-       init_rx_mode(&rm, dev, dev->mc_list);
-       t3_mac_set_rx_mode(&pi->mac, &rm);
+       t3_mac_set_rx_mode(&pi->mac, dev);
 }
 
 /**
@@ -338,17 +339,15 @@ static void cxgb_set_rxmode(struct net_device *dev)
  */
 static void link_start(struct net_device *dev)
 {
-       struct t3_rx_mode rm;
        struct port_info *pi = netdev_priv(dev);
        struct cmac *mac = &pi->mac;
 
-       init_rx_mode(&rm, dev, dev->mc_list);
        t3_mac_reset(mac);
        t3_mac_set_num_ucast(mac, MAX_MAC_IDX);
        t3_mac_set_mtu(mac, dev->mtu);
        t3_mac_set_address(mac, LAN_MAC_IDX, dev->dev_addr);
        t3_mac_set_address(mac, SAN_MAC_IDX, pi->iscsic.mac_addr);
-       t3_mac_set_rx_mode(mac, &rm);
+       t3_mac_set_rx_mode(mac, dev);
        t3_link_start(&pi->phy, mac, &pi->link_config);
        t3_mac_enable(mac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
 }
@@ -440,7 +439,7 @@ static void free_irq_resources(struct adapter *adapter)
 static int await_mgmt_replies(struct adapter *adap, unsigned long init_cnt,
                              unsigned long n)
 {
-       int attempts = 5;
+       int attempts = 10;
 
        while (adap->sge.qs[0].rspq.offload_pkts < init_cnt + n) {
                if (!--attempts)
@@ -589,6 +588,19 @@ static void setup_rss(struct adapter *adap)
                      V_RRCPLCPUSIZE(6) | F_HASHTOEPLITZ, cpus, rspq_map);
 }
 
+static void ring_dbs(struct adapter *adap)
+{
+       int i, j;
+
+       for (i = 0; i < SGE_QSETS; i++) {
+               struct sge_qset *qs = &adap->sge.qs[i];
+
+               if (qs->adap)
+                       for (j = 0; j < SGE_TXQ_PER_SET; j++)
+                               t3_write_reg(adap, A_SG_KDOORBELL, F_SELEGRCNTX | V_EGRCNTX(qs->txq[j].cntxt_id));
+       }
+}
+
 static void init_napi(struct adapter *adap)
 {
        int i;
@@ -992,11 +1004,21 @@ static int bind_qsets(struct adapter *adap)
        return err;
 }
 
-#define FW_FNAME "cxgb3/t3fw-%d.%d.%d.bin"
-#define TPSRAM_NAME "cxgb3/t3%c_psram-%d.%d.%d.bin"
+#define FW_VERSION __stringify(FW_VERSION_MAJOR) "."                   \
+       __stringify(FW_VERSION_MINOR) "." __stringify(FW_VERSION_MICRO)
+#define FW_FNAME "cxgb3/t3fw-" FW_VERSION ".bin"
+#define TPSRAM_VERSION __stringify(TP_VERSION_MAJOR) "."               \
+       __stringify(TP_VERSION_MINOR) "." __stringify(TP_VERSION_MICRO)
+#define TPSRAM_NAME "cxgb3/t3%c_psram-" TPSRAM_VERSION ".bin"
 #define AEL2005_OPT_EDC_NAME "cxgb3/ael2005_opt_edc.bin"
 #define AEL2005_TWX_EDC_NAME "cxgb3/ael2005_twx_edc.bin"
 #define AEL2020_TWX_EDC_NAME "cxgb3/ael2020_twx_edc.bin"
+MODULE_FIRMWARE(FW_FNAME);
+MODULE_FIRMWARE("cxgb3/t3b_psram-" TPSRAM_VERSION ".bin");
+MODULE_FIRMWARE("cxgb3/t3c_psram-" TPSRAM_VERSION ".bin");
+MODULE_FIRMWARE(AEL2005_OPT_EDC_NAME);
+MODULE_FIRMWARE(AEL2005_TWX_EDC_NAME);
+MODULE_FIRMWARE(AEL2020_TWX_EDC_NAME);
 
 static inline const char *get_edc_fw_name(int edc_idx)
 {
@@ -1067,16 +1089,13 @@ int t3_get_edc_fw(struct cphy *phy, int edc_idx, int size)
 static int upgrade_fw(struct adapter *adap)
 {
        int ret;
-       char buf[64];
        const struct firmware *fw;
        struct device *dev = &adap->pdev->dev;
 
-       snprintf(buf, sizeof(buf), FW_FNAME, FW_VERSION_MAJOR,
-                FW_VERSION_MINOR, FW_VERSION_MICRO);
-       ret = request_firmware(&fw, buf, dev);
+       ret = request_firmware(&fw, FW_FNAME, dev);
        if (ret < 0) {
                dev_err(dev, "could not upgrade firmware: unable to load %s\n",
-                       buf);
+                       FW_FNAME);
                return ret;
        }
        ret = t3_load_fw(adap, fw->data, fw->size);
@@ -1120,8 +1139,7 @@ static int update_tpsram(struct adapter *adap)
        if (!rev)
                return 0;
 
-       snprintf(buf, sizeof(buf), TPSRAM_NAME, rev,
-                TP_VERSION_MAJOR, TP_VERSION_MINOR, TP_VERSION_MICRO);
+       snprintf(buf, sizeof(buf), TPSRAM_NAME, rev);
 
        ret = request_firmware(&tpsram, buf, dev);
        if (ret < 0) {
@@ -1277,6 +1295,7 @@ static void cxgb_down(struct adapter *adapter)
 
        free_irq_resources(adapter);
        quiesce_rx(adapter);
+       t3_sge_stop(adapter);
        flush_workqueue(cxgb3_wq);      /* wait for external IRQ handler */
 }
 
@@ -2110,19 +2129,19 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
                if (t.qset_idx >= SGE_QSETS)
                        return -EINVAL;
                if (!in_range(t.intr_lat, 0, M_NEWTIMER) ||
-                       !in_range(t.cong_thres, 0, 255) ||
-                       !in_range(t.txq_size[0], MIN_TXQ_ENTRIES,
-                               MAX_TXQ_ENTRIES) ||
-                       !in_range(t.txq_size[1], MIN_TXQ_ENTRIES,
-                               MAX_TXQ_ENTRIES) ||
-                       !in_range(t.txq_size[2], MIN_CTRL_TXQ_ENTRIES,
-                               MAX_CTRL_TXQ_ENTRIES) ||
-                       !in_range(t.fl_size[0], MIN_FL_ENTRIES,
-                               MAX_RX_BUFFERS)
-                       || !in_range(t.fl_size[1], MIN_FL_ENTRIES,
-                                       MAX_RX_JUMBO_BUFFERS)
-                       || !in_range(t.rspq_size, MIN_RSPQ_ENTRIES,
-                                       MAX_RSPQ_ENTRIES))
+                   !in_range(t.cong_thres, 0, 255) ||
+                   !in_range(t.txq_size[0], MIN_TXQ_ENTRIES,
+                             MAX_TXQ_ENTRIES) ||
+                   !in_range(t.txq_size[1], MIN_TXQ_ENTRIES,
+                             MAX_TXQ_ENTRIES) ||
+                   !in_range(t.txq_size[2], MIN_CTRL_TXQ_ENTRIES,
+                             MAX_CTRL_TXQ_ENTRIES) ||
+                   !in_range(t.fl_size[0], MIN_FL_ENTRIES,
+                             MAX_RX_BUFFERS) ||
+                   !in_range(t.fl_size[1], MIN_FL_ENTRIES,
+                             MAX_RX_JUMBO_BUFFERS) ||
+                   !in_range(t.rspq_size, MIN_RSPQ_ENTRIES,
+                             MAX_RSPQ_ENTRIES))
                        return -EINVAL;
 
                if ((adapter->flags & FULL_INIT_DONE) && t.lro > 0)
@@ -2747,6 +2766,42 @@ static void t3_adap_check_task(struct work_struct *work)
        spin_unlock_irq(&adapter->work_lock);
 }
 
+static void db_full_task(struct work_struct *work)
+{
+       struct adapter *adapter = container_of(work, struct adapter,
+                                              db_full_task);
+
+       cxgb3_event_notify(&adapter->tdev, OFFLOAD_DB_FULL, 0);
+}
+
+static void db_empty_task(struct work_struct *work)
+{
+       struct adapter *adapter = container_of(work, struct adapter,
+                                              db_empty_task);
+
+       cxgb3_event_notify(&adapter->tdev, OFFLOAD_DB_EMPTY, 0);
+}
+
+static void db_drop_task(struct work_struct *work)
+{
+       struct adapter *adapter = container_of(work, struct adapter,
+                                              db_drop_task);
+       unsigned long delay = 1000;
+       unsigned short r;
+
+       cxgb3_event_notify(&adapter->tdev, OFFLOAD_DB_DROP, 0);
+
+       /*
+        * Sleep a while before ringing the driver qset dbs.
+        * The delay is between 1000-2023 usecs.
+        */
+       get_random_bytes(&r, 2);
+       delay += r & 1023;
+       set_current_state(TASK_UNINTERRUPTIBLE);
+       schedule_timeout(usecs_to_jiffies(delay));
+       ring_dbs(adapter);
+}
+
 /*
  * Processes external (PHY) interrupts in process context.
  */
@@ -2853,6 +2908,7 @@ static int t3_reenable_adapter(struct adapter *adapter)
        }
        pci_set_master(adapter->pdev);
        pci_restore_state(adapter->pdev);
+       pci_save_state(adapter->pdev);
 
        /* Free sge resources */
        t3_free_sge_resources(adapter);
@@ -3214,6 +3270,11 @@ static int __devinit init_one(struct pci_dev *pdev,
        INIT_LIST_HEAD(&adapter->adapter_list);
        INIT_WORK(&adapter->ext_intr_handler_task, ext_intr_task);
        INIT_WORK(&adapter->fatal_error_handler_task, fatal_error_task);
+
+       INIT_WORK(&adapter->db_full_task, db_full_task);
+       INIT_WORK(&adapter->db_empty_task, db_empty_task);
+       INIT_WORK(&adapter->db_drop_task, db_drop_task);
+
        INIT_DELAYED_WORK(&adapter->adap_check_task, t3_adap_check_task);
 
        for (i = 0; i < ai->nports0 + ai->nports1; ++i) {