]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
cxgb4: fix usage of uninitialized variable
[mirror_ubuntu-artful-kernel.git] / drivers / net / ethernet / chelsio / cxgb4 / cxgb4_main.c
index 351f3b1bf80025167c9afcc226252ec923a639b1..592a4d66169c711ccef3b94dcbc626b13fd374f5 100644 (file)
@@ -1548,7 +1548,7 @@ int cxgb4_alloc_sftid(struct tid_info *t, int family, void *data)
                t->stid_tab[stid].data = data;
                stid -= t->nstids;
                stid += t->sftid_base;
-               t->stids_in_use++;
+               t->sftids_in_use++;
        }
        spin_unlock_bh(&t->stid_lock);
        return stid;
@@ -1573,10 +1573,14 @@ void cxgb4_free_stid(struct tid_info *t, unsigned int stid, int family)
        else
                bitmap_release_region(t->stid_bmap, stid, 2);
        t->stid_tab[stid].data = NULL;
-       if (family == PF_INET)
-               t->stids_in_use--;
-       else
-               t->stids_in_use -= 4;
+       if (stid < t->nstids) {
+               if (family == PF_INET)
+                       t->stids_in_use--;
+               else
+                       t->stids_in_use -= 4;
+       } else {
+               t->sftids_in_use--;
+       }
        spin_unlock_bh(&t->stid_lock);
 }
 EXPORT_SYMBOL(cxgb4_free_stid);
@@ -1654,20 +1658,25 @@ static void process_tid_release_list(struct work_struct *work)
  */
 void cxgb4_remove_tid(struct tid_info *t, unsigned int chan, unsigned int tid)
 {
-       void *old;
        struct sk_buff *skb;
        struct adapter *adap = container_of(t, struct adapter, tids);
 
-       old = t->tid_tab[tid];
+       WARN_ON(tid >= t->ntids);
+
+       if (t->tid_tab[tid]) {
+               t->tid_tab[tid] = NULL;
+               if (t->hash_base && (tid >= t->hash_base))
+                       atomic_dec(&t->hash_tids_in_use);
+               else
+                       atomic_dec(&t->tids_in_use);
+       }
+
        skb = alloc_skb(sizeof(struct cpl_tid_release), GFP_ATOMIC);
        if (likely(skb)) {
-               t->tid_tab[tid] = NULL;
                mk_tid_release(skb, chan, tid);
                t4_ofld_send(adap, skb);
        } else
                cxgb4_queue_tid_release(t, chan, tid);
-       if (old)
-               atomic_dec(&t->tids_in_use);
 }
 EXPORT_SYMBOL(cxgb4_remove_tid);
 
@@ -1702,9 +1711,11 @@ static int tid_init(struct tid_info *t)
        spin_lock_init(&t->atid_lock);
 
        t->stids_in_use = 0;
+       t->sftids_in_use = 0;
        t->afree = NULL;
        t->atids_in_use = 0;
        atomic_set(&t->tids_in_use, 0);
+       atomic_set(&t->hash_tids_in_use, 0);
 
        /* Setup the free list for atid_tab and clear the stid bitmap. */
        if (natids) {
@@ -3657,6 +3668,10 @@ static int adap_init0(struct adapter *adap)
         */
        t4_get_fw_version(adap, &adap->params.fw_vers);
        t4_get_tp_version(adap, &adap->params.tp_vers);
+       ret = t4_check_fw_version(adap);
+       /* If firmware is too old (not supported by driver) force an update. */
+       if (ret == -EFAULT)
+               state = DEV_STATE_UNINIT;
        if ((adap->flags & MASTER_PF) && state != DEV_STATE_INIT) {
                struct fw_info *fw_info;
                struct fw_hdr *card_fw;
@@ -4551,6 +4566,27 @@ static void free_some_resources(struct adapter *adapter)
                   NETIF_F_IPV6_CSUM | NETIF_F_HIGHDMA)
 #define SEGMENT_SIZE 128
 
+static int get_chip_type(struct pci_dev *pdev, u32 pl_rev)
+{
+       u16 device_id;
+
+       /* Retrieve adapter's device ID */
+       pci_read_config_word(pdev, PCI_DEVICE_ID, &device_id);
+
+       switch (device_id >> 12) {
+       case CHELSIO_T4:
+               return CHELSIO_CHIP_CODE(CHELSIO_T4, pl_rev);
+       case CHELSIO_T5:
+               return CHELSIO_CHIP_CODE(CHELSIO_T5, pl_rev);
+       case CHELSIO_T6:
+               return CHELSIO_CHIP_CODE(CHELSIO_T6, pl_rev);
+       default:
+               dev_err(&pdev->dev, "Device %d is not supported\n",
+                       device_id);
+       }
+       return -EINVAL;
+}
+
 static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        int func, i, err, s_qpp, qpp, num_seg;
@@ -4558,6 +4594,8 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        bool highdma = false;
        struct adapter *adapter = NULL;
        void __iomem *regs;
+       u32 whoami, pl_rev;
+       enum chip_type chip;
 
        printk_once(KERN_INFO "%s - version %s\n", DRV_DESC, DRV_VERSION);
 
@@ -4586,7 +4624,11 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                goto out_unmap_bar0;
 
        /* We control everything through one PF */
-       func = SOURCEPF_G(readl(regs + PL_WHOAMI_A));
+       whoami = readl(regs + PL_WHOAMI_A);
+       pl_rev = REV_G(readl(regs + PL_REV_A));
+       chip = get_chip_type(pdev, pl_rev);
+       func = CHELSIO_CHIP_VERSION(chip) <= CHELSIO_T5 ?
+               SOURCEPF_G(whoami) : T6_SOURCEPF_G(whoami);
        if (func != ent->driver_data) {
                iounmap(regs);
                pci_disable_device(pdev);
@@ -4757,7 +4799,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
         */
        cfg_queues(adapter);
 
-       adapter->l2t = t4_init_l2t();
+       adapter->l2t = t4_init_l2t(adapter->l2t_start, adapter->l2t_end);
        if (!adapter->l2t) {
                /* We tolerate a lack of L2T, giving up some functionality */
                dev_warn(&pdev->dev, "could not allocate L2T, continuing\n");
@@ -4782,6 +4824,22 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                adapter->params.offload = 0;
        }
 
+       if (is_offload(adapter)) {
+               if (t4_read_reg(adapter, LE_DB_CONFIG_A) & HASHEN_F) {
+                       u32 hash_base, hash_reg;
+
+                       if (chip <= CHELSIO_T5) {
+                               hash_reg = LE_DB_TID_HASHBASE_A;
+                               hash_base = t4_read_reg(adapter, hash_reg);
+                               adapter->tids.hash_base = hash_base / 4;
+                       } else {
+                               hash_reg = T6_LE_DB_HASH_TID_BASE_A;
+                               hash_base = t4_read_reg(adapter, hash_reg);
+                               adapter->tids.hash_base = hash_base;
+                       }
+               }
+       }
+
        /* See what interrupts we'll be using */
        if (msi > 1 && enable_msix(adapter) == 0)
                adapter->flags |= USING_MSIX;