cxgb4: fix error recovery when t4_fw_hello returns a positive value
[linux-2.6-microblaze.git] / drivers / net / ethernet / chelsio / cxgb4 / cxgb4_main.c
index 6a6a01a..3cd397d 100644 (file)
@@ -229,44 +229,44 @@ static DEFINE_PCI_DEVICE_TABLE(cxgb4_pci_tbl) = {
        CH_DEVICE(0x440a, 4),
        CH_DEVICE(0x440d, 4),
        CH_DEVICE(0x440e, 4),
-       CH_DEVICE(0x5001, 5),
-       CH_DEVICE(0x5002, 5),
-       CH_DEVICE(0x5003, 5),
-       CH_DEVICE(0x5004, 5),
-       CH_DEVICE(0x5005, 5),
-       CH_DEVICE(0x5006, 5),
-       CH_DEVICE(0x5007, 5),
-       CH_DEVICE(0x5008, 5),
-       CH_DEVICE(0x5009, 5),
-       CH_DEVICE(0x500A, 5),
-       CH_DEVICE(0x500B, 5),
-       CH_DEVICE(0x500C, 5),
-       CH_DEVICE(0x500D, 5),
-       CH_DEVICE(0x500E, 5),
-       CH_DEVICE(0x500F, 5),
-       CH_DEVICE(0x5010, 5),
-       CH_DEVICE(0x5011, 5),
-       CH_DEVICE(0x5012, 5),
-       CH_DEVICE(0x5013, 5),
-       CH_DEVICE(0x5401, 5),
-       CH_DEVICE(0x5402, 5),
-       CH_DEVICE(0x5403, 5),
-       CH_DEVICE(0x5404, 5),
-       CH_DEVICE(0x5405, 5),
-       CH_DEVICE(0x5406, 5),
-       CH_DEVICE(0x5407, 5),
-       CH_DEVICE(0x5408, 5),
-       CH_DEVICE(0x5409, 5),
-       CH_DEVICE(0x540A, 5),
-       CH_DEVICE(0x540B, 5),
-       CH_DEVICE(0x540C, 5),
-       CH_DEVICE(0x540D, 5),
-       CH_DEVICE(0x540E, 5),
-       CH_DEVICE(0x540F, 5),
-       CH_DEVICE(0x5410, 5),
-       CH_DEVICE(0x5411, 5),
-       CH_DEVICE(0x5412, 5),
-       CH_DEVICE(0x5413, 5),
+       CH_DEVICE(0x5001, 4),
+       CH_DEVICE(0x5002, 4),
+       CH_DEVICE(0x5003, 4),
+       CH_DEVICE(0x5004, 4),
+       CH_DEVICE(0x5005, 4),
+       CH_DEVICE(0x5006, 4),
+       CH_DEVICE(0x5007, 4),
+       CH_DEVICE(0x5008, 4),
+       CH_DEVICE(0x5009, 4),
+       CH_DEVICE(0x500A, 4),
+       CH_DEVICE(0x500B, 4),
+       CH_DEVICE(0x500C, 4),
+       CH_DEVICE(0x500D, 4),
+       CH_DEVICE(0x500E, 4),
+       CH_DEVICE(0x500F, 4),
+       CH_DEVICE(0x5010, 4),
+       CH_DEVICE(0x5011, 4),
+       CH_DEVICE(0x5012, 4),
+       CH_DEVICE(0x5013, 4),
+       CH_DEVICE(0x5401, 4),
+       CH_DEVICE(0x5402, 4),
+       CH_DEVICE(0x5403, 4),
+       CH_DEVICE(0x5404, 4),
+       CH_DEVICE(0x5405, 4),
+       CH_DEVICE(0x5406, 4),
+       CH_DEVICE(0x5407, 4),
+       CH_DEVICE(0x5408, 4),
+       CH_DEVICE(0x5409, 4),
+       CH_DEVICE(0x540A, 4),
+       CH_DEVICE(0x540B, 4),
+       CH_DEVICE(0x540C, 4),
+       CH_DEVICE(0x540D, 4),
+       CH_DEVICE(0x540E, 4),
+       CH_DEVICE(0x540F, 4),
+       CH_DEVICE(0x5410, 4),
+       CH_DEVICE(0x5411, 4),
+       CH_DEVICE(0x5412, 4),
+       CH_DEVICE(0x5413, 4),
        { 0, }
 };
 
@@ -645,6 +645,21 @@ static int fwevtq_handler(struct sge_rspq *q, const __be64 *rsp,
        u8 opcode = ((const struct rss_header *)rsp)->opcode;
 
        rsp++;                                          /* skip RSS header */
+
+       /* FW can send EGR_UPDATEs encapsulated in a CPL_FW4_MSG.
+        */
+       if (unlikely(opcode == CPL_FW4_MSG &&
+          ((const struct cpl_fw4_msg *)rsp)->type == FW_TYPE_RSSCPL)) {
+               rsp++;
+               opcode = ((const struct rss_header *)rsp)->opcode;
+               rsp++;
+               if (opcode != CPL_SGE_EGR_UPDATE) {
+                       dev_err(q->adap->pdev_dev, "unexpected FW4/CPL %#x on FW event queue\n"
+                               , opcode);
+                       goto out;
+               }
+       }
+
        if (likely(opcode == CPL_SGE_EGR_UPDATE)) {
                const struct cpl_sge_egr_update *p = (void *)rsp;
                unsigned int qid = EGR_QID(ntohl(p->opcode_qid));
@@ -679,6 +694,7 @@ static int fwevtq_handler(struct sge_rspq *q, const __be64 *rsp,
        } else
                dev_err(q->adap->pdev_dev,
                        "unexpected CPL %#x on FW event queue\n", opcode);
+out:
        return 0;
 }
 
@@ -696,6 +712,12 @@ static int uldrx_handler(struct sge_rspq *q, const __be64 *rsp,
 {
        struct sge_ofld_rxq *rxq = container_of(q, struct sge_ofld_rxq, rspq);
 
+       /* FW can send CPLs encapsulated in a CPL_FW4_MSG.
+        */
+       if (((const struct rss_header *)rsp)->opcode == CPL_FW4_MSG &&
+           ((const struct cpl_fw4_msg *)(rsp + 1))->type == FW_TYPE_RSSCPL)
+               rsp += 2;
+
        if (ulds[q->uld].rx_handler(q->adap->uld_handle[q->uld], rsp, gl)) {
                rxq->stats.nomem++;
                return -1;
@@ -4990,6 +5012,15 @@ static int adap_init0(struct adapter *adap)
                adap->tids.aftid_end = val[1];
        }
 
+       /* If we're running on newer firmware, let it know that we're
+        * prepared to deal with encapsulated CPL messages.  Older
+        * firmware won't understand this and we'll just get
+        * unencapsulated messages ...
+        */
+       params[0] = FW_PARAM_PFVF(CPLFW4MSG_ENCAP);
+       val[0] = 1;
+       (void) t4_set_params(adap, adap->mbox, adap->fn, 0, 1, params, val);
+
        /*
         * Get device capabilities so we can determine what resources we need
         * to manage.
@@ -5173,7 +5204,7 @@ static pci_ers_result_t eeh_slot_reset(struct pci_dev *pdev)
 
        if (t4_wait_dev_ready(adap) < 0)
                return PCI_ERS_RESULT_DISCONNECT;
-       if (t4_fw_hello(adap, adap->fn, adap->fn, MASTER_MUST, NULL))
+       if (t4_fw_hello(adap, adap->fn, adap->fn, MASTER_MUST, NULL) < 0)
                return PCI_ERS_RESULT_DISCONNECT;
        adap->flags |= FW_OK;
        if (adap_init1(adap, &c))