[SCSI] lpfc 8.3.5: fix VPI registration, error clean up and add support for vlink...
authorJames Smart <James.Smart@Emulex.Com>
Fri, 2 Oct 2009 19:16:45 +0000 (15:16 -0400)
committerJames Bottomley <James.Bottomley@suse.de>
Fri, 4 Dec 2009 18:01:40 +0000 (12:01 -0600)
This patch includes the following fixes and new features:
- Fix mask size for CT field in WQE
- Fix VPI base not used when unregistering VPI on port 1.
- Fix UNREG_VPI mailbox command to unreg the correct VPI
- Fixed Check for aborted els command
- Fix error when trying to load driver with wrong firmware on FCoE HBA.
- Fix bug with probe_one routines not putting the Scsi_Host back upon error
- Add support for Clear Virtual Link Async Events
- Add support for unsolicited CT exchange sequence abort
- Add 0x0714 OCeXXXXX PCI ID

Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
drivers/scsi/lpfc/lpfc_crtn.h
drivers/scsi/lpfc/lpfc_ct.c
drivers/scsi/lpfc/lpfc_els.c
drivers/scsi/lpfc/lpfc_hbadisc.c
drivers/scsi/lpfc/lpfc_hw.h
drivers/scsi/lpfc/lpfc_hw4.h
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_mbox.c
drivers/scsi/lpfc/lpfc_sli.c
drivers/scsi/lpfc/lpfc_sli.h
drivers/scsi/lpfc/lpfc_sli4.h

index 4438f8665a4a293078e8c9893d4ee396e84fc2bc..0d450ae3a2d437aace0b245da2228c9b9cc7523e 100644 (file)
@@ -144,6 +144,8 @@ void lpfc_hb_timeout_handler(struct lpfc_hba *);
 
 void lpfc_ct_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *,
                         struct lpfc_iocbq *);
+void lpfc_sli4_ct_abort_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *,
+                                   struct lpfc_iocbq *);
 int lpfc_ns_cmd(struct lpfc_vport *, int, uint8_t, uint32_t);
 int lpfc_fdmi_cmd(struct lpfc_vport *, struct lpfc_nodelist *, int);
 void lpfc_fdmi_tmo(unsigned long);
@@ -188,7 +190,7 @@ int lpfc_mbox_tmo_val(struct lpfc_hba *, int);
 void lpfc_init_vfi(struct lpfcMboxq *, struct lpfc_vport *);
 void lpfc_reg_vfi(struct lpfcMboxq *, struct lpfc_vport *, dma_addr_t);
 void lpfc_init_vpi(struct lpfc_hba *, struct lpfcMboxq *, uint16_t);
-void lpfc_unreg_vfi(struct lpfcMboxq *, uint16_t);
+void lpfc_unreg_vfi(struct lpfcMboxq *, struct lpfc_vport *);
 void lpfc_reg_fcfi(struct lpfc_hba *, struct lpfcMboxq *);
 void lpfc_unreg_fcfi(struct lpfcMboxq *, uint16_t);
 void lpfc_resume_rpi(struct lpfcMboxq *, struct lpfc_nodelist *);
@@ -361,6 +363,7 @@ void lpfc_stop_port(struct lpfc_hba *);
 void lpfc_parse_fcoe_conf(struct lpfc_hba *, uint8_t *, uint32_t);
 int lpfc_parse_vpd(struct lpfc_hba *, uint8_t *, int);
 void lpfc_start_fdiscs(struct lpfc_hba *phba);
+struct lpfc_vport *lpfc_find_vport_by_vpid(struct lpfc_hba *, uint16_t);
 
 #define ScsiResult(host_code, scsi_code) (((host_code) << 16) | scsi_code)
 #define HBA_EVENT_RSCN                   5
index 9a1bd9534d744fd2e3454ea3c8ff67673324e02b..e724048bf3902b8aec501492024c05ffeebb2472 100644 (file)
@@ -87,7 +87,6 @@ void
 lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                    struct lpfc_iocbq *piocbq)
 {
-
        struct lpfc_dmabuf *mp = NULL;
        IOCB_t *icmd = &piocbq->iocb;
        int i;
@@ -160,6 +159,39 @@ lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
        }
 }
 
+/**
+ * lpfc_sli4_ct_abort_unsol_event - Default handle for sli4 unsol abort
+ * @phba: Pointer to HBA context object.
+ * @pring: Pointer to the driver internal I/O ring.
+ * @piocbq: Pointer to the IOCBQ.
+ *
+ * This function serves as the default handler for the sli4 unsolicited
+ * abort event. It shall be invoked when there is no application interface
+ * registered unsolicited abort handler. This handler does nothing but
+ * just simply releases the dma buffer used by the unsol abort event.
+ **/
+void
+lpfc_sli4_ct_abort_unsol_event(struct lpfc_hba *phba,
+                              struct lpfc_sli_ring *pring,
+                              struct lpfc_iocbq *piocbq)
+{
+       IOCB_t *icmd = &piocbq->iocb;
+       struct lpfc_dmabuf *bdeBuf;
+       uint32_t size;
+
+       /* Forward abort event to any process registered to receive ct event */
+       lpfc_bsg_ct_unsol_event(phba, pring, piocbq);
+
+       /* If there is no BDE associated with IOCB, there is nothing to do */
+       if (icmd->ulpBdeCount == 0)
+               return;
+       bdeBuf = piocbq->context2;
+       piocbq->context2 = NULL;
+       size  = icmd->un.cont64[0].tus.f.bdeSize;
+       lpfc_ct_unsol_buffer(phba, piocbq, bdeBuf, size);
+       lpfc_in_buf_free(phba, bdeBuf);
+}
+
 static void
 lpfc_free_ct_rsp(struct lpfc_hba *phba, struct lpfc_dmabuf *mlist)
 {
index 4ea863f50650906ebf2c8f61a2c6934ac8b38e61..489ddcd4c58424a643536be5b08b2bf97f98c7b9 100644 (file)
@@ -2712,12 +2712,16 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
            !lpfc_error_lost_link(irsp)) {
                /* FLOGI retry policy */
                retry = 1;
-               maxretry = 48;
-               if (cmdiocb->retry >= 32)
+               /* retry forever */
+               maxretry = 0;
+               if (cmdiocb->retry >= 100)
+                       delay = 5000;
+               else if (cmdiocb->retry >= 32)
                        delay = 1000;
        }
 
-       if ((++cmdiocb->retry) >= maxretry) {
+       cmdiocb->retry++;
+       if (maxretry && (cmdiocb->retry >= maxretry)) {
                phba->fc_stat.elsRetryExceeded++;
                retry = 0;
        }
@@ -5671,7 +5675,7 @@ dropit:
  *    NULL - No vport with the matching @vpi found
  *    Otherwise - Address to the vport with the matching @vpi.
  **/
-static struct lpfc_vport *
+struct lpfc_vport *
 lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t vpi)
 {
        struct lpfc_vport *vport;
index 5073c127bfe122870c315f19244c3ba70488e96e..1b2771ac15f2cc3eee6887597c71514f47e39e6d 100644 (file)
@@ -4474,7 +4474,7 @@ lpfc_unregister_unused_fcf(struct lpfc_hba *phba)
                return;
        }
 
-       lpfc_unreg_vfi(mbox, phba->pport->vfi);
+       lpfc_unreg_vfi(mbox, phba->pport);
        mbox->vport = phba->pport;
        mbox->mbox_cmpl = lpfc_unregister_vfi_cmpl;
 
index ccb26724dc538c70bc528d6f9a14336b0d1de222..74f9f028b45f7c8ebf8a5950160dc36294599308 100644 (file)
@@ -1183,6 +1183,7 @@ typedef struct {
 #define PCI_DEVICE_ID_ZEPHYR_DCSP   0xfe12
 #define PCI_VENDOR_ID_SERVERENGINE  0x19a2
 #define PCI_DEVICE_ID_TIGERSHARK    0x0704
+#define PCI_DEVICE_ID_TS_BE3        0x0714
 
 #define JEDEC_ID_ADDRESS            0x0080001c
 #define FIREFLY_JEDEC_ID            0x1ACC
@@ -1444,6 +1445,7 @@ typedef struct {          /* FireFly BIU registers */
 #define CMD_ABORT_MXRI64_CN     0x8C
 #define CMD_RCV_ELS_REQ64_CX    0x8D
 #define CMD_XMIT_ELS_RSP64_CX   0x95
+#define CMD_XMIT_BLS_RSP64_CX   0x97
 #define CMD_FCP_IWRITE64_CR     0x98
 #define CMD_FCP_IWRITE64_CX     0x99
 #define CMD_FCP_IREAD64_CR      0x9A
@@ -2326,7 +2328,13 @@ typedef struct {
 /* Structure for MB Command UNREG_VPI (0x97) */
 typedef struct {
        uint32_t rsvd1;
-       uint32_t rsvd2;
+#ifdef __BIG_ENDIAN_BITFIELD
+       uint16_t rsvd2;
+       uint16_t sli4_vpi;
+#else  /*  __LITTLE_ENDIAN */
+       uint16_t sli4_vpi;
+       uint16_t rsvd2;
+#endif
        uint32_t rsvd3;
        uint32_t rsvd4;
        uint32_t rsvd5;
index 3689eee0453575a3a115f5bb08fef0fca248dbd2..0c65091110cc58bfc5a02d82c2f6ad63cf5c0098 100644 (file)
@@ -425,7 +425,7 @@ struct lpfc_wqe_generic{
 #define lpfc_wqe_gen_status_MASK       0x0000000F
 #define lpfc_wqe_gen_status_WORD       word7
 #define lpfc_wqe_gen_ct_SHIFT          2
-#define lpfc_wqe_gen_ct_MASK           0x00000007
+#define lpfc_wqe_gen_ct_MASK           0x00000003
 #define lpfc_wqe_gen_ct_WORD           word7
        uint32_t abort_tag;
        uint32_t word9;
@@ -760,6 +760,7 @@ struct mbox_header {
 #define LPFC_MBOX_OPCODE_MQ_DESTROY            0x35
 #define LPFC_MBOX_OPCODE_CQ_DESTROY            0x36
 #define LPFC_MBOX_OPCODE_EQ_DESTROY            0x37
+#define LPFC_MBOX_OPCODE_QUERY_FW_CFG          0x3A
 #define LPFC_MBOX_OPCODE_FUNCTION_RESET                0x3D
 
 /* FCoE Opcodes */
@@ -1273,6 +1274,51 @@ struct lpfc_mbx_del_fcf_tbl_entry {
 #define lpfc_mbx_del_fcf_tbl_index_WORD                word10
 };
 
+struct lpfc_mbx_query_fw_cfg {
+       struct mbox_header header;
+       uint32_t config_number;
+       uint32_t asic_rev;
+       uint32_t phys_port;
+       uint32_t function_mode;
+/* firmware Function Mode */
+#define lpfc_function_mode_toe_SHIFT           0
+#define lpfc_function_mode_toe_MASK            0x00000001
+#define lpfc_function_mode_toe_WORD            function_mode
+#define lpfc_function_mode_nic_SHIFT           1
+#define lpfc_function_mode_nic_MASK            0x00000001
+#define lpfc_function_mode_nic_WORD            function_mode
+#define lpfc_function_mode_rdma_SHIFT          2
+#define lpfc_function_mode_rdma_MASK           0x00000001
+#define lpfc_function_mode_rdma_WORD           function_mode
+#define lpfc_function_mode_vm_SHIFT            3
+#define lpfc_function_mode_vm_MASK             0x00000001
+#define lpfc_function_mode_vm_WORD             function_mode
+#define lpfc_function_mode_iscsi_i_SHIFT       4
+#define lpfc_function_mode_iscsi_i_MASK                0x00000001
+#define lpfc_function_mode_iscsi_i_WORD                function_mode
+#define lpfc_function_mode_iscsi_t_SHIFT       5
+#define lpfc_function_mode_iscsi_t_MASK                0x00000001
+#define lpfc_function_mode_iscsi_t_WORD                function_mode
+#define lpfc_function_mode_fcoe_i_SHIFT                6
+#define lpfc_function_mode_fcoe_i_MASK         0x00000001
+#define lpfc_function_mode_fcoe_i_WORD         function_mode
+#define lpfc_function_mode_fcoe_t_SHIFT                7
+#define lpfc_function_mode_fcoe_t_MASK         0x00000001
+#define lpfc_function_mode_fcoe_t_WORD         function_mode
+#define lpfc_function_mode_dal_SHIFT           8
+#define lpfc_function_mode_dal_MASK            0x00000001
+#define lpfc_function_mode_dal_WORD            function_mode
+#define lpfc_function_mode_lro_SHIFT           9
+#define lpfc_function_mode_lro_MASK            0x00000001
+#define lpfc_function_mode_lro_WORD            function_mode9
+#define lpfc_function_mode_flex10_SHIFT                10
+#define lpfc_function_mode_flex10_MASK         0x00000001
+#define lpfc_function_mode_flex10_WORD         function_mode
+#define lpfc_function_mode_ncsi_SHIFT          11
+#define lpfc_function_mode_ncsi_MASK           0x00000001
+#define lpfc_function_mode_ncsi_WORD           function_mode
+};
+
 /* Status field for embedded SLI_CONFIG mailbox command */
 #define STATUS_SUCCESS                                 0x0
 #define STATUS_FAILED                                  0x1
@@ -1804,6 +1850,7 @@ struct lpfc_mqe {
                struct lpfc_mbx_read_config rd_config;
                struct lpfc_mbx_request_features req_ftrs;
                struct lpfc_mbx_post_hdr_tmpl hdr_tmpl;
+               struct lpfc_mbx_query_fw_cfg query_fw_cfg;
                struct lpfc_mbx_nop nop;
        } un;
 };
@@ -1885,7 +1932,7 @@ struct lpfc_acqe_link {
 };
 
 struct lpfc_acqe_fcoe {
-       uint32_t fcf_index;
+       uint32_t index;
        uint32_t word1;
 #define lpfc_acqe_fcoe_fcf_count_SHIFT         0
 #define lpfc_acqe_fcoe_fcf_count_MASK          0x0000FFFF
@@ -1896,6 +1943,7 @@ struct lpfc_acqe_fcoe {
 #define LPFC_FCOE_EVENT_TYPE_NEW_FCF           0x1
 #define LPFC_FCOE_EVENT_TYPE_FCF_TABLE_FULL    0x2
 #define LPFC_FCOE_EVENT_TYPE_FCF_DEAD          0x3
+#define LPFC_FCOE_EVENT_TYPE_CVL               0x4
        uint32_t event_tag;
        uint32_t trailer;
 };
@@ -1924,9 +1972,9 @@ struct lpfc_bmbx_create {
 #define NO_XRI ((uint16_t)-1)
 struct wqe_common {
        uint32_t word6;
-#define wqe_xri_SHIFT         0
-#define wqe_xri_MASK          0x0000FFFF
-#define wqe_xri_WORD          word6
+#define wqe_xri_tag_SHIFT     0
+#define wqe_xri_tag_MASK      0x0000FFFF
+#define wqe_xri_tag_WORD      word6
 #define wqe_ctxt_tag_SHIFT    16
 #define wqe_ctxt_tag_MASK     0x0000FFFF
 #define wqe_ctxt_tag_WORD     word6
@@ -1987,7 +2035,7 @@ struct wqe_common {
 #define wqe_wqec_MASK       0x00000001
 #define wqe_wqec_WORD       word11
 #define wqe_cqid_SHIFT      16
-#define wqe_cqid_MASK       0x000003ff
+#define wqe_cqid_MASK       0x0000ffff
 #define wqe_cqid_WORD       word11
 };
 
@@ -1996,6 +2044,9 @@ struct wqe_did {
 #define wqe_els_did_SHIFT         0
 #define wqe_els_did_MASK          0x00FFFFFF
 #define wqe_els_did_WORD          word5
+#define wqe_xmit_bls_pt_SHIFT         28
+#define wqe_xmit_bls_pt_MASK          0x00000003
+#define wqe_xmit_bls_pt_WORD          word5
 #define wqe_xmit_bls_ar_SHIFT         30
 #define wqe_xmit_bls_ar_MASK          0x00000001
 #define wqe_xmit_bls_ar_WORD          word5
@@ -2044,6 +2095,23 @@ struct xmit_els_rsp64_wqe {
 
 struct xmit_bls_rsp64_wqe {
        uint32_t payload0;
+/* Payload0 for BA_ACC */
+#define xmit_bls_rsp64_acc_seq_id_SHIFT        16
+#define xmit_bls_rsp64_acc_seq_id_MASK         0x000000ff
+#define xmit_bls_rsp64_acc_seq_id_WORD         payload0
+#define xmit_bls_rsp64_acc_seq_id_vald_SHIFT   24
+#define xmit_bls_rsp64_acc_seq_id_vald_MASK    0x000000ff
+#define xmit_bls_rsp64_acc_seq_id_vald_WORD    payload0
+/* Payload0 for BA_RJT */
+#define xmit_bls_rsp64_rjt_vspec_SHIFT   0
+#define xmit_bls_rsp64_rjt_vspec_MASK    0x000000ff
+#define xmit_bls_rsp64_rjt_vspec_WORD    payload0
+#define xmit_bls_rsp64_rjt_expc_SHIFT    8
+#define xmit_bls_rsp64_rjt_expc_MASK     0x000000ff
+#define xmit_bls_rsp64_rjt_expc_WORD     payload0
+#define xmit_bls_rsp64_rjt_rsnc_SHIFT    16
+#define xmit_bls_rsp64_rjt_rsnc_MASK     0x000000ff
+#define xmit_bls_rsp64_rjt_rsnc_WORD     payload0
        uint32_t word1;
 #define xmit_bls_rsp64_rxid_SHIFT  0
 #define xmit_bls_rsp64_rxid_MASK   0x0000ffff
@@ -2052,18 +2120,19 @@ struct xmit_bls_rsp64_wqe {
 #define xmit_bls_rsp64_oxid_MASK   0x0000ffff
 #define xmit_bls_rsp64_oxid_WORD   word1
        uint32_t word2;
-#define xmit_bls_rsp64_seqcntlo_SHIFT  0
-#define xmit_bls_rsp64_seqcntlo_MASK   0x0000ffff
-#define xmit_bls_rsp64_seqcntlo_WORD   word2
-#define xmit_bls_rsp64_seqcnthi_SHIFT  16
+#define xmit_bls_rsp64_seqcnthi_SHIFT  0
 #define xmit_bls_rsp64_seqcnthi_MASK   0x0000ffff
 #define xmit_bls_rsp64_seqcnthi_WORD   word2
+#define xmit_bls_rsp64_seqcntlo_SHIFT  16
+#define xmit_bls_rsp64_seqcntlo_MASK   0x0000ffff
+#define xmit_bls_rsp64_seqcntlo_WORD   word2
        uint32_t rsrvd3;
        uint32_t rsrvd4;
        struct wqe_did  wqe_dest;
        struct wqe_common wqe_com; /* words 6-11 */
        uint32_t rsvd_12_15[4];
 };
+
 struct wqe_rctl_dfctl {
        uint32_t word5;
 #define wqe_si_SHIFT 2
index d654c0e3db4d214b8436112f97fc709218fa2689..a7b5566ea0b56185da54b5d7639e2bf141b5cf6b 100644 (file)
@@ -1669,6 +1669,10 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
                oneConnect = 1;
                m = (typeof(m)) {"OCe10100-F", max_speed, "PCIe"};
                break;
+       case PCI_DEVICE_ID_TS_BE3:
+               oneConnect = 1;
+               m = (typeof(m)) {"OCeXXXXX-F", max_speed, "PCIe"};
+               break;
        default:
                m = (typeof(m)){ NULL };
                break;
@@ -2698,6 +2702,63 @@ lpfc_sli_remove_dflt_fcf(struct lpfc_hba *phba)
                mempool_free(mboxq, phba->mbox_mem_pool);
 }
 
+/**
+ * lpfc_sli4_fw_cfg_check - Read the firmware config and verify FCoE support
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This function uses the QUERY_FW_CFG mailbox command to determine if the
+ * firmware loaded supports FCoE. A return of zero indicates that the mailbox
+ * was successful and the firmware supports FCoE. Any other return indicates
+ * a error. It is assumed that this function will be called before interrupts
+ * are enabled.
+ **/
+static int
+lpfc_sli4_fw_cfg_check(struct lpfc_hba *phba)
+{
+       int rc = 0;
+       LPFC_MBOXQ_t *mboxq;
+       struct lpfc_mbx_query_fw_cfg *query_fw_cfg;
+       uint32_t length;
+       uint32_t shdr_status, shdr_add_status;
+
+       mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+       if (!mboxq) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                               "2621 Failed to allocate mbox for "
+                               "query firmware config cmd\n");
+               return -ENOMEM;
+       }
+       query_fw_cfg = &mboxq->u.mqe.un.query_fw_cfg;
+       length = (sizeof(struct lpfc_mbx_query_fw_cfg) -
+                 sizeof(struct lpfc_sli4_cfg_mhdr));
+       lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON,
+                        LPFC_MBOX_OPCODE_QUERY_FW_CFG,
+                        length, LPFC_SLI4_MBX_EMBED);
+       rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
+       /* The IOCTL status is embedded in the mailbox subheader. */
+       shdr_status = bf_get(lpfc_mbox_hdr_status,
+                            &query_fw_cfg->header.cfg_shdr.response);
+       shdr_add_status = bf_get(lpfc_mbox_hdr_add_status,
+                                &query_fw_cfg->header.cfg_shdr.response);
+       if (shdr_status || shdr_add_status || rc != MBX_SUCCESS) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+                               "2622 Query Firmware Config failed "
+                               "mbx status x%x, status x%x add_status x%x\n",
+                               rc, shdr_status, shdr_add_status);
+               return -EINVAL;
+       }
+       if (!bf_get(lpfc_function_mode_fcoe_i, query_fw_cfg)) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+                               "2623 FCoE Function not supported by firmware. "
+                               "Function mode = %08x\n",
+                               query_fw_cfg->function_mode);
+               return -EINVAL;
+       }
+       if (rc != MBX_TIMEOUT)
+               mempool_free(mboxq, phba->mbox_mem_pool);
+       return 0;
+}
+
 /**
  * lpfc_sli4_parse_latt_fault - Parse sli4 link-attention link fault code
  * @phba: pointer to lpfc hba data structure.
@@ -2918,6 +2979,9 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
 {
        uint8_t event_type = bf_get(lpfc_acqe_fcoe_event_type, acqe_fcoe);
        int rc;
+       struct lpfc_vport *vport;
+       struct lpfc_nodelist *ndlp;
+       struct Scsi_Host  *shost;
 
        phba->fc_eventTag = acqe_fcoe->event_tag;
        phba->fcoe_eventtag = acqe_fcoe->event_tag;
@@ -2925,7 +2989,7 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
        case LPFC_FCOE_EVENT_TYPE_NEW_FCF:
                lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
                        "2546 New FCF found index 0x%x tag 0x%x\n",
-                       acqe_fcoe->fcf_index,
+                       acqe_fcoe->index,
                        acqe_fcoe->event_tag);
                /*
                 * If the current FCF is in discovered state, or
@@ -2958,10 +3022,10 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
        case LPFC_FCOE_EVENT_TYPE_FCF_DEAD:
                lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
                        "2549 FCF disconnected fron network index 0x%x"
-                       " tag 0x%x\n", acqe_fcoe->fcf_index,
+                       " tag 0x%x\n", acqe_fcoe->index,
                        acqe_fcoe->event_tag);
                /* If the event is not for currently used fcf do nothing */
-               if (phba->fcf.fcf_indx != acqe_fcoe->fcf_index)
+               if (phba->fcf.fcf_indx != acqe_fcoe->index)
                        break;
                /*
                 * Currently, driver support only one FCF - so treat this as
@@ -2971,7 +3035,28 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
                /* Unregister FCF if no devices connected to it */
                lpfc_unregister_unused_fcf(phba);
                break;
-
+       case LPFC_FCOE_EVENT_TYPE_CVL:
+               lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+                       "2718 Clear Virtual Link Received for VPI 0x%x"
+                       " tag 0x%x\n", acqe_fcoe->index, acqe_fcoe->event_tag);
+               vport = lpfc_find_vport_by_vpid(phba,
+                               acqe_fcoe->index /*- phba->vpi_base*/);
+               if (!vport)
+                       break;
+               ndlp = lpfc_findnode_did(vport, Fabric_DID);
+               if (!ndlp)
+                       break;
+               shost = lpfc_shost_from_vport(vport);
+               lpfc_linkdown_port(vport);
+               if (vport->port_type != LPFC_NPIV_PORT) {
+                       mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
+                       spin_lock_irq(shost->host_lock);
+                       ndlp->nlp_flag |= NLP_DELAY_TMO;
+                       spin_unlock_irq(shost->host_lock);
+                       ndlp->nlp_last_elscmd = ELS_CMD_FLOGI;
+                       vport->port_state = LPFC_FLOGI;
+               }
+               break;
        default:
                lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
                        "0288 Unknown FCoE event type 0x%x event tag "
@@ -3463,6 +3548,10 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
        if (unlikely(rc))
                goto out_free_bsmbx;
 
+       rc = lpfc_sli4_fw_cfg_check(phba);
+       if (unlikely(rc))
+               goto out_free_bsmbx;
+
        /* Set up the hba's configuration parameters. */
        rc = lpfc_sli4_read_config(phba);
        if (unlikely(rc))
@@ -6687,6 +6776,7 @@ lpfc_pci_probe_one_s3(struct pci_dev *pdev, const struct pci_device_id *pid)
 {
        struct lpfc_hba   *phba;
        struct lpfc_vport *vport = NULL;
+       struct Scsi_Host  *shost = NULL;
        int error;
        uint32_t cfg_mode, intr_mode;
 
@@ -6765,6 +6855,7 @@ lpfc_pci_probe_one_s3(struct pci_dev *pdev, const struct pci_device_id *pid)
                goto out_destroy_shost;
        }
 
+       shost = lpfc_shost_from_vport(vport); /* save shost for error cleanup */
        /* Now, trying to enable interrupt and bring up the device */
        cfg_mode = phba->cfg_use_msi;
        while (true) {
@@ -6831,6 +6922,8 @@ out_unset_pci_mem_s3:
        lpfc_sli_pci_mem_unset(phba);
 out_disable_pci_dev:
        lpfc_disable_pci_dev(phba);
+       if (shost)
+               scsi_host_put(shost);
 out_free_phba:
        lpfc_hba_free(phba);
        return error;
@@ -7214,6 +7307,7 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
 {
        struct lpfc_hba   *phba;
        struct lpfc_vport *vport = NULL;
+       struct Scsi_Host  *shost = NULL;
        int error;
        uint32_t cfg_mode, intr_mode;
        int mcnt;
@@ -7294,6 +7388,7 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
                goto out_destroy_shost;
        }
 
+       shost = lpfc_shost_from_vport(vport); /* save shost for error cleanup */
        /* Now, trying to enable interrupt and bring up the device */
        cfg_mode = phba->cfg_use_msi;
        while (true) {
@@ -7362,6 +7457,8 @@ out_unset_pci_mem_s4:
        lpfc_sli4_pci_mem_unset(phba);
 out_disable_pci_dev:
        lpfc_disable_pci_dev(phba);
+       if (shost)
+               scsi_host_put(shost);
 out_free_phba:
        lpfc_hba_free(phba);
        return error;
@@ -7936,6 +8033,8 @@ static struct pci_device_id lpfc_id_table[] = {
                PCI_ANY_ID, PCI_ANY_ID, },
        {PCI_VENDOR_ID_SERVERENGINE, PCI_DEVICE_ID_TIGERSHARK,
                PCI_ANY_ID, PCI_ANY_ID, },
+       {PCI_VENDOR_ID_SERVERENGINE, PCI_DEVICE_ID_TS_BE3,
+               PCI_ANY_ID, PCI_ANY_ID, },
        { 0 }
 };
 
index 1ab405902a1879a0f196013c3598614152a73412..2a38d94654bc06553674db0653dd3bf5378bdc67 100644 (file)
@@ -849,7 +849,10 @@ lpfc_unreg_vpi(struct lpfc_hba *phba, uint16_t vpi, LPFC_MBOXQ_t *pmb)
        MAILBOX_t *mb = &pmb->u.mb;
        memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
 
-       mb->un.varUnregVpi.vpi = vpi + phba->vpi_base;
+       if (phba->sli_rev < LPFC_SLI_REV4)
+               mb->un.varUnregVpi.vpi = vpi + phba->vpi_base;
+       else
+               mb->un.varUnregVpi.sli4_vpi = vpi + phba->vpi_base;
 
        mb->mbxCommand = MBX_UNREG_VPI;
        mb->mbxOwner = OWN_HOST;
@@ -1850,7 +1853,7 @@ lpfc_init_vpi(struct lpfc_hba *phba, struct lpfcMboxq *mbox, uint16_t vpi)
 /**
  * lpfc_unreg_vfi - Initialize the UNREG_VFI mailbox command
  * @mbox: pointer to lpfc mbox command to initialize.
- * @vfi: VFI to be unregistered.
+ * @vport: vport associated with the VF.
  *
  * The UNREG_VFI mailbox command causes the SLI Host to put a virtual fabric
  * (logical NPort) into the inactive state. The SLI Host must have logged out
@@ -1859,11 +1862,12 @@ lpfc_init_vpi(struct lpfc_hba *phba, struct lpfcMboxq *mbox, uint16_t vpi)
  * fabric inactive.
  **/
 void
-lpfc_unreg_vfi(struct lpfcMboxq *mbox, uint16_t vfi)
+lpfc_unreg_vfi(struct lpfcMboxq *mbox, struct lpfc_vport *vport)
 {
        memset(mbox, 0, sizeof(*mbox));
        bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_UNREG_VFI);
-       bf_set(lpfc_unreg_vfi_vfi, &mbox->u.mqe.un.unreg_vfi, vfi);
+       bf_set(lpfc_unreg_vfi_vfi, &mbox->u.mqe.un.unreg_vfi,
+              vport->vfi + vport->phba->vfi_base);
 }
 
 /**
index 8d884d8e18be3149ff9f11157a4ae415fe987580..e8d3e4732a846b3f37499ee3bb9cbdd18993f689 100644 (file)
@@ -59,7 +59,8 @@ static int lpfc_sli_issue_mbox_s4(struct lpfc_hba *, LPFC_MBOXQ_t *,
                                  uint32_t);
 static int lpfc_sli4_read_rev(struct lpfc_hba *, LPFC_MBOXQ_t *,
                            uint8_t *, uint32_t *);
-
+static void lpfc_sli4_send_seq_to_ulp(struct lpfc_vport *,
+                                     struct hbq_dmabuf *);
 static IOCB_t *
 lpfc_get_iocb_from_iocbq(struct lpfc_iocbq *iocbq)
 {
@@ -572,9 +573,9 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
                sglq = __lpfc_clear_active_sglq(phba, iocbq->sli4_xritag);
        if (sglq)  {
                if (iocbq->iocb_flag & LPFC_DRIVER_ABORTED
-                       || ((iocbq->iocb.ulpStatus == IOSTAT_LOCAL_REJECT)
+                       && ((iocbq->iocb.ulpStatus == IOSTAT_LOCAL_REJECT)
                        && (iocbq->iocb.un.ulpWord[4]
-                               == IOERR_SLI_ABORTED))) {
+                               == IOERR_ABORT_REQUESTED))) {
                        spin_lock_irqsave(&phba->sli4_hba.abts_sgl_list_lock,
                                        iflag);
                        list_add(&sglq->list,
@@ -767,6 +768,7 @@ lpfc_sli_iocb_cmd_type(uint8_t iocb_cmnd)
        case CMD_CLOSE_XRI_CX:
        case CMD_XRI_ABORTED_CX:
        case CMD_ABORT_MXRI64_CN:
+       case CMD_XMIT_BLS_RSP64_CX:
                type = LPFC_ABORT_IOCB;
                break;
        case CMD_RCV_SEQUENCE_CX:
@@ -6081,6 +6083,23 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
                command_type = OTHER_COMMAND;
                xritag = 0;
        break;
+       case CMD_XMIT_BLS_RSP64_CX:
+               /* As BLS ABTS-ACC WQE is very different from other WQEs,
+                * we re-construct this WQE here based on information in
+                * iocbq from scratch.
+                */
+               memset(wqe, 0, sizeof(union lpfc_wqe));
+               bf_set(xmit_bls_rsp64_oxid, &wqe->xmit_bls_rsp,
+                      iocbq->iocb.un.ulpWord[3]);
+               bf_set(xmit_bls_rsp64_rxid, &wqe->xmit_bls_rsp,
+                      iocbq->sli4_xritag);
+               bf_set(xmit_bls_rsp64_seqcnthi, &wqe->xmit_bls_rsp, 0xffff);
+               bf_set(wqe_xmit_bls_pt, &wqe->xmit_bls_rsp.wqe_dest, 0x1);
+               bf_set(wqe_ctxt_tag, &wqe->xmit_bls_rsp.wqe_com,
+                      iocbq->iocb.ulpContext);
+               /* Overwrite the pre-set comnd type with OTHER_COMMAND */
+               command_type = OTHER_COMMAND;
+       break;
        case CMD_XRI_ABORTED_CX:
        case CMD_CREATE_XRI_CR: /* Do we expect to use this? */
                /* words0-2 are all 0's no bde */
@@ -6139,7 +6158,7 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number,
 
        if (piocb->sli4_xritag == NO_XRI) {
                if (piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN ||
-                       piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN)
+                   piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN)
                        sglq = NULL;
                else {
                        sglq = __lpfc_sli_get_sglq(phba);
@@ -6464,7 +6483,7 @@ lpfc_sli_setup(struct lpfc_hba *phba)
                        pring->iotag_max = 4096;
                        pring->lpfc_sli_rcv_async_status =
                                lpfc_sli_async_event_handler;
-                       pring->num_mask = 4;
+                       pring->num_mask = LPFC_MAX_RING_MASK;
                        pring->prt[0].profile = 0;      /* Mask 0 */
                        pring->prt[0].rctl = FC_ELS_REQ;
                        pring->prt[0].type = FC_ELS_DATA;
@@ -6489,6 +6508,12 @@ lpfc_sli_setup(struct lpfc_hba *phba)
                        pring->prt[3].type = FC_COMMON_TRANSPORT_ULP;
                        pring->prt[3].lpfc_sli_rcv_unsol_event =
                            lpfc_ct_unsol_event;
+                       /* abort unsolicited sequence */
+                       pring->prt[4].profile = 0;      /* Mask 4 */
+                       pring->prt[4].rctl = FC_RCTL_BA_ABTS;
+                       pring->prt[4].type = FC_TYPE_BLS;
+                       pring->prt[4].lpfc_sli_rcv_unsol_event =
+                           lpfc_sli4_ct_abort_unsol_event;
                        break;
                }
                totiocbsize += (pring->numCiocb * pring->sizeCiocb) +
@@ -10869,6 +10894,177 @@ lpfc_fc_frame_add(struct lpfc_vport *vport, struct hbq_dmabuf *dmabuf)
        return NULL;
 }
 
+/**
+ * lpfc_sli4_abort_partial_seq - Abort partially assembled unsol sequence
+ * @vport: pointer to a vitural port
+ * @dmabuf: pointer to a dmabuf that describes the FC sequence
+ *
+ * This function tries to abort from the partially assembed sequence, described
+ * by the information from basic abbort @dmabuf. It checks to see whether such
+ * partially assembled sequence held by the driver. If so, it shall free up all
+ * the frames from the partially assembled sequence.
+ *
+ * Return
+ * true  -- if there is matching partially assembled sequence present and all
+ *          the frames freed with the sequence;
+ * false -- if there is no matching partially assembled sequence present so
+ *          nothing got aborted in the lower layer driver
+ **/
+static bool
+lpfc_sli4_abort_partial_seq(struct lpfc_vport *vport,
+                           struct hbq_dmabuf *dmabuf)
+{
+       struct fc_frame_header *new_hdr;
+       struct fc_frame_header *temp_hdr;
+       struct lpfc_dmabuf *d_buf, *n_buf, *h_buf;
+       struct hbq_dmabuf *seq_dmabuf = NULL;
+
+       /* Use the hdr_buf to find the sequence that matches this frame */
+       INIT_LIST_HEAD(&dmabuf->dbuf.list);
+       INIT_LIST_HEAD(&dmabuf->hbuf.list);
+       new_hdr = (struct fc_frame_header *)dmabuf->hbuf.virt;
+       list_for_each_entry(h_buf, &vport->rcv_buffer_list, list) {
+               temp_hdr = (struct fc_frame_header *)h_buf->virt;
+               if ((temp_hdr->fh_seq_id != new_hdr->fh_seq_id) ||
+                   (temp_hdr->fh_ox_id != new_hdr->fh_ox_id) ||
+                   (memcmp(&temp_hdr->fh_s_id, &new_hdr->fh_s_id, 3)))
+                       continue;
+               /* found a pending sequence that matches this frame */
+               seq_dmabuf = container_of(h_buf, struct hbq_dmabuf, hbuf);
+               break;
+       }
+
+       /* Free up all the frames from the partially assembled sequence */
+       if (seq_dmabuf) {
+               list_for_each_entry_safe(d_buf, n_buf,
+                                        &seq_dmabuf->dbuf.list, list) {
+                       list_del_init(&d_buf->list);
+                       lpfc_in_buf_free(vport->phba, d_buf);
+               }
+               return true;
+       }
+       return false;
+}
+
+/**
+ * lpfc_sli4_seq_abort_acc_cmpl - Accept seq abort iocb complete handler
+ * @phba: Pointer to HBA context object.
+ * @cmd_iocbq: pointer to the command iocbq structure.
+ * @rsp_iocbq: pointer to the response iocbq structure.
+ *
+ * This function handles the sequence abort accept iocb command complete
+ * event. It properly releases the memory allocated to the sequence abort
+ * accept iocb.
+ **/
+static void
+lpfc_sli4_seq_abort_acc_cmpl(struct lpfc_hba *phba,
+                            struct lpfc_iocbq *cmd_iocbq,
+                            struct lpfc_iocbq *rsp_iocbq)
+{
+       if (cmd_iocbq)
+               lpfc_sli_release_iocbq(phba, cmd_iocbq);
+}
+
+/**
+ * lpfc_sli4_seq_abort_acc - Accept sequence abort
+ * @phba: Pointer to HBA context object.
+ * @fc_hdr: pointer to a FC frame header.
+ *
+ * This function sends a basic accept to a previous unsol sequence abort
+ * event after aborting the sequence handling.
+ **/
+static void
+lpfc_sli4_seq_abort_acc(struct lpfc_hba *phba,
+                       struct fc_frame_header *fc_hdr)
+{
+       struct lpfc_iocbq *ctiocb = NULL;
+       struct lpfc_nodelist *ndlp;
+       uint16_t oxid;
+       uint32_t sid;
+       IOCB_t *icmd;
+
+       if (!lpfc_is_link_up(phba))
+               return;
+
+       sid = sli4_sid_from_fc_hdr(fc_hdr);
+       oxid = be16_to_cpu(fc_hdr->fh_ox_id);
+
+       ndlp = lpfc_findnode_did(phba->pport, sid);
+       if (!ndlp) {
+               lpfc_printf_log(phba, KERN_WARNING, LOG_ELS,
+                               "1268 Find ndlp returned NULL for oxid:x%x "
+                               "SID:x%x\n", oxid, sid);
+               return;
+       }
+
+       /* Allocate buffer for acc iocb */
+       ctiocb = lpfc_sli_get_iocbq(phba);
+       if (!ctiocb)
+               return;
+
+       icmd = &ctiocb->iocb;
+       icmd->un.xseq64.bdl.ulpIoTag32 = 0;
+       icmd->un.xseq64.bdl.bdeSize = 0;
+       icmd->un.xseq64.w5.hcsw.Dfctl = 0;
+       icmd->un.xseq64.w5.hcsw.Rctl = FC_RCTL_BA_ACC;
+       icmd->un.xseq64.w5.hcsw.Type = FC_TYPE_BLS;
+
+       /* Fill in the rest of iocb fields */
+       icmd->ulpCommand = CMD_XMIT_BLS_RSP64_CX;
+       icmd->ulpBdeCount = 0;
+       icmd->ulpLe = 1;
+       icmd->ulpClass = CLASS3;
+       icmd->ulpContext = ndlp->nlp_rpi;
+       icmd->un.ulpWord[3] = oxid;
+
+       ctiocb->sli4_xritag = NO_XRI;
+       ctiocb->iocb_cmpl = NULL;
+       ctiocb->vport = phba->pport;
+       ctiocb->iocb_cmpl = lpfc_sli4_seq_abort_acc_cmpl;
+
+       /* Xmit CT abts accept on exchange <xid> */
+       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+                       "1200 Xmit CT ABTS ACC on exchange x%x Data: x%x\n",
+                       CMD_XMIT_BLS_RSP64_CX, phba->link_state);
+       lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, ctiocb, 0);
+}
+
+/**
+ * lpfc_sli4_handle_unsol_abort - Handle sli-4 unsolicited abort event
+ * @vport: Pointer to the vport on which this sequence was received
+ * @dmabuf: pointer to a dmabuf that describes the FC sequence
+ *
+ * This function handles an SLI-4 unsolicited abort event. If the unsolicited
+ * receive sequence is only partially assembed by the driver, it shall abort
+ * the partially assembled frames for the sequence. Otherwise, if the
+ * unsolicited receive sequence has been completely assembled and passed to
+ * the Upper Layer Protocol (UPL), it then mark the per oxid status for the
+ * unsolicited sequence has been aborted. After that, it will issue a basic
+ * accept to accept the abort.
+ **/
+void
+lpfc_sli4_handle_unsol_abort(struct lpfc_vport *vport,
+                            struct hbq_dmabuf *dmabuf)
+{
+       struct lpfc_hba *phba = vport->phba;
+       struct fc_frame_header fc_hdr;
+       bool abts_par;
+
+       /* Try to abort partially assembled seq */
+       abts_par = lpfc_sli4_abort_partial_seq(vport, dmabuf);
+
+       /* Make a copy of fc_hdr before the dmabuf being released */
+       memcpy(&fc_hdr, dmabuf->hbuf.virt, sizeof(struct fc_frame_header));
+
+       /* Send abort to ULP if partially seq abort failed */
+       if (abts_par == false)
+               lpfc_sli4_send_seq_to_ulp(vport, dmabuf);
+       else
+               lpfc_in_buf_free(phba, &dmabuf->dbuf);
+       /* Send basic accept (BA_ACC) to the abort requester */
+       lpfc_sli4_seq_abort_acc(phba, &fc_hdr);
+}
+
 /**
  * lpfc_seq_complete - Indicates if a sequence is complete
  * @dmabuf: pointer to a dmabuf that describes the FC sequence
@@ -10941,9 +11137,7 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf)
        /* remove from receive buffer list */
        list_del_init(&seq_dmabuf->hbuf.list);
        /* get the Remote Port's SID */
-       sid = (fc_hdr->fh_s_id[0] << 16 |
-              fc_hdr->fh_s_id[1] << 8 |
-              fc_hdr->fh_s_id[2]);
+       sid = sli4_sid_from_fc_hdr(fc_hdr);
        /* Get an iocbq struct to fill in. */
        first_iocbq = lpfc_sli_get_iocbq(vport->phba);
        if (first_iocbq) {
@@ -11010,6 +11204,43 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf)
        return first_iocbq;
 }
 
+static void
+lpfc_sli4_send_seq_to_ulp(struct lpfc_vport *vport,
+                         struct hbq_dmabuf *seq_dmabuf)
+{
+       struct fc_frame_header *fc_hdr;
+       struct lpfc_iocbq *iocbq, *curr_iocb, *next_iocb;
+       struct lpfc_hba *phba = vport->phba;
+
+       fc_hdr = (struct fc_frame_header *)seq_dmabuf->hbuf.virt;
+       iocbq = lpfc_prep_seq(vport, seq_dmabuf);
+       if (!iocbq) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+                               "2707 Ring %d handler: Failed to allocate "
+                               "iocb Rctl x%x Type x%x received\n",
+                               LPFC_ELS_RING,
+                               fc_hdr->fh_r_ctl, fc_hdr->fh_type);
+               return;
+       }
+       if (!lpfc_complete_unsol_iocb(phba,
+                                     &phba->sli.ring[LPFC_ELS_RING],
+                                     iocbq, fc_hdr->fh_r_ctl,
+                                     fc_hdr->fh_type))
+               lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+                               "2540 Ring %d handler: unexpected Rctl "
+                               "x%x Type x%x received\n",
+                               LPFC_ELS_RING,
+                               fc_hdr->fh_r_ctl, fc_hdr->fh_type);
+
+       /* Free iocb created in lpfc_prep_seq */
+       list_for_each_entry_safe(curr_iocb, next_iocb,
+               &iocbq->list, list) {
+               list_del_init(&curr_iocb->list);
+               lpfc_sli_release_iocbq(phba, curr_iocb);
+       }
+       lpfc_sli_release_iocbq(phba, iocbq);
+}
+
 /**
  * lpfc_sli4_handle_received_buffer - Handle received buffers from firmware
  * @phba: Pointer to HBA context object.
@@ -11030,7 +11261,6 @@ lpfc_sli4_handle_received_buffer(struct lpfc_hba *phba,
        struct fc_frame_header *fc_hdr;
        struct lpfc_vport *vport;
        uint32_t fcfi;
-       struct lpfc_iocbq *iocbq;
 
        /* Clear hba flag and get all received buffers into the cmplq */
        spin_lock_irq(&phba->hbalock);
@@ -11051,6 +11281,12 @@ lpfc_sli4_handle_received_buffer(struct lpfc_hba *phba,
                lpfc_in_buf_free(phba, &dmabuf->dbuf);
                return;
        }
+       /* Handle the basic abort sequence (BA_ABTS) event */
+       if (fc_hdr->fh_r_ctl == FC_RCTL_BA_ABTS) {
+               lpfc_sli4_handle_unsol_abort(vport, dmabuf);
+               return;
+       }
+
        /* Link this frame */
        seq_dmabuf = lpfc_fc_frame_add(vport, dmabuf);
        if (!seq_dmabuf) {
@@ -11068,17 +11304,8 @@ lpfc_sli4_handle_received_buffer(struct lpfc_hba *phba,
                dmabuf->tag = -1;
                return;
        }
-       fc_hdr = (struct fc_frame_header *)seq_dmabuf->hbuf.virt;
-       iocbq = lpfc_prep_seq(vport, seq_dmabuf);
-       if (!lpfc_complete_unsol_iocb(phba,
-                                     &phba->sli.ring[LPFC_ELS_RING],
-                                     iocbq, fc_hdr->fh_r_ctl,
-                                     fc_hdr->fh_type))
-               lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
-                               "2540 Ring %d handler: unexpected Rctl "
-                               "x%x Type x%x received\n",
-                               LPFC_ELS_RING,
-                               fc_hdr->fh_r_ctl, fc_hdr->fh_type);
+       /* Send the complete sequence to the upper layer protocol */
+       lpfc_sli4_send_seq_to_ulp(vport, seq_dmabuf);
 }
 
 /**
index ad8094966ff34e29ed1301e824ee1c62e4a353a5..0e518b12f414e72b0d183bf0060441f710a56f5c 100644 (file)
@@ -113,7 +113,7 @@ typedef struct lpfcMboxq {
                                   return */
 #define MBX_NOWAIT      2      /* issue command then return immediately */
 
-#define LPFC_MAX_RING_MASK  4  /* max num of rctl/type masks allowed per
+#define LPFC_MAX_RING_MASK  5  /* max num of rctl/type masks allowed per
                                   ring */
 #define LPFC_MAX_RING       4  /* max num of SLI rings used by driver */
 
index 97da7589e0387f59c72047bffa4a223c5403e520..fc3de6fdd70967e5db6da88622966db99d6f9492 100644 (file)
 #define LPFC_FCOE_FKA_ADV_PER  0
 #define LPFC_FCOE_FIP_PRIORITY 0x80
 
+#define sli4_sid_from_fc_hdr(fc_hdr)  \
+       ((fc_hdr)->fh_s_id[0] << 16 | \
+        (fc_hdr)->fh_s_id[1] <<  8 | \
+        (fc_hdr)->fh_s_id[2])
+
 enum lpfc_sli4_queue_type {
        LPFC_EQ,
        LPFC_GCQ,