diff options
author | James Smart <James.Smart@Emulex.Com> | 2009-10-02 15:16:45 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2009-12-04 13:01:40 -0500 |
commit | 6669f9bb902b8c3f5e33cb8c32c8c0eec6ed68ed (patch) | |
tree | e143e916abc71ff3c7edb7a5508d480391efc1ee /drivers/scsi/lpfc/lpfc_sli.c | |
parent | 4d9ab994e214d35107017c342aca42477b137316 (diff) |
[SCSI] lpfc 8.3.5: fix VPI registration, error clean up and add support for vlink events
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>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_sli.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 267 |
1 files changed, 247 insertions, 20 deletions
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 8d884d8e18be..e8d3e4732a84 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -59,7 +59,8 @@ static int lpfc_sli_issue_mbox_s4(struct lpfc_hba *, LPFC_MBOXQ_t *, | |||
59 | uint32_t); | 59 | uint32_t); |
60 | static int lpfc_sli4_read_rev(struct lpfc_hba *, LPFC_MBOXQ_t *, | 60 | static int lpfc_sli4_read_rev(struct lpfc_hba *, LPFC_MBOXQ_t *, |
61 | uint8_t *, uint32_t *); | 61 | uint8_t *, uint32_t *); |
62 | 62 | static void lpfc_sli4_send_seq_to_ulp(struct lpfc_vport *, | |
63 | struct hbq_dmabuf *); | ||
63 | static IOCB_t * | 64 | static IOCB_t * |
64 | lpfc_get_iocb_from_iocbq(struct lpfc_iocbq *iocbq) | 65 | lpfc_get_iocb_from_iocbq(struct lpfc_iocbq *iocbq) |
65 | { | 66 | { |
@@ -572,9 +573,9 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) | |||
572 | sglq = __lpfc_clear_active_sglq(phba, iocbq->sli4_xritag); | 573 | sglq = __lpfc_clear_active_sglq(phba, iocbq->sli4_xritag); |
573 | if (sglq) { | 574 | if (sglq) { |
574 | if (iocbq->iocb_flag & LPFC_DRIVER_ABORTED | 575 | if (iocbq->iocb_flag & LPFC_DRIVER_ABORTED |
575 | || ((iocbq->iocb.ulpStatus == IOSTAT_LOCAL_REJECT) | 576 | && ((iocbq->iocb.ulpStatus == IOSTAT_LOCAL_REJECT) |
576 | && (iocbq->iocb.un.ulpWord[4] | 577 | && (iocbq->iocb.un.ulpWord[4] |
577 | == IOERR_SLI_ABORTED))) { | 578 | == IOERR_ABORT_REQUESTED))) { |
578 | spin_lock_irqsave(&phba->sli4_hba.abts_sgl_list_lock, | 579 | spin_lock_irqsave(&phba->sli4_hba.abts_sgl_list_lock, |
579 | iflag); | 580 | iflag); |
580 | list_add(&sglq->list, | 581 | list_add(&sglq->list, |
@@ -767,6 +768,7 @@ lpfc_sli_iocb_cmd_type(uint8_t iocb_cmnd) | |||
767 | case CMD_CLOSE_XRI_CX: | 768 | case CMD_CLOSE_XRI_CX: |
768 | case CMD_XRI_ABORTED_CX: | 769 | case CMD_XRI_ABORTED_CX: |
769 | case CMD_ABORT_MXRI64_CN: | 770 | case CMD_ABORT_MXRI64_CN: |
771 | case CMD_XMIT_BLS_RSP64_CX: | ||
770 | type = LPFC_ABORT_IOCB; | 772 | type = LPFC_ABORT_IOCB; |
771 | break; | 773 | break; |
772 | case CMD_RCV_SEQUENCE_CX: | 774 | case CMD_RCV_SEQUENCE_CX: |
@@ -6081,6 +6083,23 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, | |||
6081 | command_type = OTHER_COMMAND; | 6083 | command_type = OTHER_COMMAND; |
6082 | xritag = 0; | 6084 | xritag = 0; |
6083 | break; | 6085 | break; |
6086 | case CMD_XMIT_BLS_RSP64_CX: | ||
6087 | /* As BLS ABTS-ACC WQE is very different from other WQEs, | ||
6088 | * we re-construct this WQE here based on information in | ||
6089 | * iocbq from scratch. | ||
6090 | */ | ||
6091 | memset(wqe, 0, sizeof(union lpfc_wqe)); | ||
6092 | bf_set(xmit_bls_rsp64_oxid, &wqe->xmit_bls_rsp, | ||
6093 | iocbq->iocb.un.ulpWord[3]); | ||
6094 | bf_set(xmit_bls_rsp64_rxid, &wqe->xmit_bls_rsp, | ||
6095 | iocbq->sli4_xritag); | ||
6096 | bf_set(xmit_bls_rsp64_seqcnthi, &wqe->xmit_bls_rsp, 0xffff); | ||
6097 | bf_set(wqe_xmit_bls_pt, &wqe->xmit_bls_rsp.wqe_dest, 0x1); | ||
6098 | bf_set(wqe_ctxt_tag, &wqe->xmit_bls_rsp.wqe_com, | ||
6099 | iocbq->iocb.ulpContext); | ||
6100 | /* Overwrite the pre-set comnd type with OTHER_COMMAND */ | ||
6101 | command_type = OTHER_COMMAND; | ||
6102 | break; | ||
6084 | case CMD_XRI_ABORTED_CX: | 6103 | case CMD_XRI_ABORTED_CX: |
6085 | case CMD_CREATE_XRI_CR: /* Do we expect to use this? */ | 6104 | case CMD_CREATE_XRI_CR: /* Do we expect to use this? */ |
6086 | /* words0-2 are all 0's no bde */ | 6105 | /* 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, | |||
6139 | 6158 | ||
6140 | if (piocb->sli4_xritag == NO_XRI) { | 6159 | if (piocb->sli4_xritag == NO_XRI) { |
6141 | if (piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN || | 6160 | if (piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN || |
6142 | piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN) | 6161 | piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN) |
6143 | sglq = NULL; | 6162 | sglq = NULL; |
6144 | else { | 6163 | else { |
6145 | sglq = __lpfc_sli_get_sglq(phba); | 6164 | sglq = __lpfc_sli_get_sglq(phba); |
@@ -6464,7 +6483,7 @@ lpfc_sli_setup(struct lpfc_hba *phba) | |||
6464 | pring->iotag_max = 4096; | 6483 | pring->iotag_max = 4096; |
6465 | pring->lpfc_sli_rcv_async_status = | 6484 | pring->lpfc_sli_rcv_async_status = |
6466 | lpfc_sli_async_event_handler; | 6485 | lpfc_sli_async_event_handler; |
6467 | pring->num_mask = 4; | 6486 | pring->num_mask = LPFC_MAX_RING_MASK; |
6468 | pring->prt[0].profile = 0; /* Mask 0 */ | 6487 | pring->prt[0].profile = 0; /* Mask 0 */ |
6469 | pring->prt[0].rctl = FC_ELS_REQ; | 6488 | pring->prt[0].rctl = FC_ELS_REQ; |
6470 | pring->prt[0].type = FC_ELS_DATA; | 6489 | pring->prt[0].type = FC_ELS_DATA; |
@@ -6489,6 +6508,12 @@ lpfc_sli_setup(struct lpfc_hba *phba) | |||
6489 | pring->prt[3].type = FC_COMMON_TRANSPORT_ULP; | 6508 | pring->prt[3].type = FC_COMMON_TRANSPORT_ULP; |
6490 | pring->prt[3].lpfc_sli_rcv_unsol_event = | 6509 | pring->prt[3].lpfc_sli_rcv_unsol_event = |
6491 | lpfc_ct_unsol_event; | 6510 | lpfc_ct_unsol_event; |
6511 | /* abort unsolicited sequence */ | ||
6512 | pring->prt[4].profile = 0; /* Mask 4 */ | ||
6513 | pring->prt[4].rctl = FC_RCTL_BA_ABTS; | ||
6514 | pring->prt[4].type = FC_TYPE_BLS; | ||
6515 | pring->prt[4].lpfc_sli_rcv_unsol_event = | ||
6516 | lpfc_sli4_ct_abort_unsol_event; | ||
6492 | break; | 6517 | break; |
6493 | } | 6518 | } |
6494 | totiocbsize += (pring->numCiocb * pring->sizeCiocb) + | 6519 | totiocbsize += (pring->numCiocb * pring->sizeCiocb) + |
@@ -10870,6 +10895,177 @@ lpfc_fc_frame_add(struct lpfc_vport *vport, struct hbq_dmabuf *dmabuf) | |||
10870 | } | 10895 | } |
10871 | 10896 | ||
10872 | /** | 10897 | /** |
10898 | * lpfc_sli4_abort_partial_seq - Abort partially assembled unsol sequence | ||
10899 | * @vport: pointer to a vitural port | ||
10900 | * @dmabuf: pointer to a dmabuf that describes the FC sequence | ||
10901 | * | ||
10902 | * This function tries to abort from the partially assembed sequence, described | ||
10903 | * by the information from basic abbort @dmabuf. It checks to see whether such | ||
10904 | * partially assembled sequence held by the driver. If so, it shall free up all | ||
10905 | * the frames from the partially assembled sequence. | ||
10906 | * | ||
10907 | * Return | ||
10908 | * true -- if there is matching partially assembled sequence present and all | ||
10909 | * the frames freed with the sequence; | ||
10910 | * false -- if there is no matching partially assembled sequence present so | ||
10911 | * nothing got aborted in the lower layer driver | ||
10912 | **/ | ||
10913 | static bool | ||
10914 | lpfc_sli4_abort_partial_seq(struct lpfc_vport *vport, | ||
10915 | struct hbq_dmabuf *dmabuf) | ||
10916 | { | ||
10917 | struct fc_frame_header *new_hdr; | ||
10918 | struct fc_frame_header *temp_hdr; | ||
10919 | struct lpfc_dmabuf *d_buf, *n_buf, *h_buf; | ||
10920 | struct hbq_dmabuf *seq_dmabuf = NULL; | ||
10921 | |||
10922 | /* Use the hdr_buf to find the sequence that matches this frame */ | ||
10923 | INIT_LIST_HEAD(&dmabuf->dbuf.list); | ||
10924 | INIT_LIST_HEAD(&dmabuf->hbuf.list); | ||
10925 | new_hdr = (struct fc_frame_header *)dmabuf->hbuf.virt; | ||
10926 | list_for_each_entry(h_buf, &vport->rcv_buffer_list, list) { | ||
10927 | temp_hdr = (struct fc_frame_header *)h_buf->virt; | ||
10928 | if ((temp_hdr->fh_seq_id != new_hdr->fh_seq_id) || | ||
10929 | (temp_hdr->fh_ox_id != new_hdr->fh_ox_id) || | ||
10930 | (memcmp(&temp_hdr->fh_s_id, &new_hdr->fh_s_id, 3))) | ||
10931 | continue; | ||
10932 | /* found a pending sequence that matches this frame */ | ||
10933 | seq_dmabuf = container_of(h_buf, struct hbq_dmabuf, hbuf); | ||
10934 | break; | ||
10935 | } | ||
10936 | |||
10937 | /* Free up all the frames from the partially assembled sequence */ | ||
10938 | if (seq_dmabuf) { | ||
10939 | list_for_each_entry_safe(d_buf, n_buf, | ||
10940 | &seq_dmabuf->dbuf.list, list) { | ||
10941 | list_del_init(&d_buf->list); | ||
10942 | lpfc_in_buf_free(vport->phba, d_buf); | ||
10943 | } | ||
10944 | return true; | ||
10945 | } | ||
10946 | return false; | ||
10947 | } | ||
10948 | |||
10949 | /** | ||
10950 | * lpfc_sli4_seq_abort_acc_cmpl - Accept seq abort iocb complete handler | ||
10951 | * @phba: Pointer to HBA context object. | ||
10952 | * @cmd_iocbq: pointer to the command iocbq structure. | ||
10953 | * @rsp_iocbq: pointer to the response iocbq structure. | ||
10954 | * | ||
10955 | * This function handles the sequence abort accept iocb command complete | ||
10956 | * event. It properly releases the memory allocated to the sequence abort | ||
10957 | * accept iocb. | ||
10958 | **/ | ||
10959 | static void | ||
10960 | lpfc_sli4_seq_abort_acc_cmpl(struct lpfc_hba *phba, | ||
10961 | struct lpfc_iocbq *cmd_iocbq, | ||
10962 | struct lpfc_iocbq *rsp_iocbq) | ||
10963 | { | ||
10964 | if (cmd_iocbq) | ||
10965 | lpfc_sli_release_iocbq(phba, cmd_iocbq); | ||
10966 | } | ||
10967 | |||
10968 | /** | ||
10969 | * lpfc_sli4_seq_abort_acc - Accept sequence abort | ||
10970 | * @phba: Pointer to HBA context object. | ||
10971 | * @fc_hdr: pointer to a FC frame header. | ||
10972 | * | ||
10973 | * This function sends a basic accept to a previous unsol sequence abort | ||
10974 | * event after aborting the sequence handling. | ||
10975 | **/ | ||
10976 | static void | ||
10977 | lpfc_sli4_seq_abort_acc(struct lpfc_hba *phba, | ||
10978 | struct fc_frame_header *fc_hdr) | ||
10979 | { | ||
10980 | struct lpfc_iocbq *ctiocb = NULL; | ||
10981 | struct lpfc_nodelist *ndlp; | ||
10982 | uint16_t oxid; | ||
10983 | uint32_t sid; | ||
10984 | IOCB_t *icmd; | ||
10985 | |||
10986 | if (!lpfc_is_link_up(phba)) | ||
10987 | return; | ||
10988 | |||
10989 | sid = sli4_sid_from_fc_hdr(fc_hdr); | ||
10990 | oxid = be16_to_cpu(fc_hdr->fh_ox_id); | ||
10991 | |||
10992 | ndlp = lpfc_findnode_did(phba->pport, sid); | ||
10993 | if (!ndlp) { | ||
10994 | lpfc_printf_log(phba, KERN_WARNING, LOG_ELS, | ||
10995 | "1268 Find ndlp returned NULL for oxid:x%x " | ||
10996 | "SID:x%x\n", oxid, sid); | ||
10997 | return; | ||
10998 | } | ||
10999 | |||
11000 | /* Allocate buffer for acc iocb */ | ||
11001 | ctiocb = lpfc_sli_get_iocbq(phba); | ||
11002 | if (!ctiocb) | ||
11003 | return; | ||
11004 | |||
11005 | icmd = &ctiocb->iocb; | ||
11006 | icmd->un.xseq64.bdl.ulpIoTag32 = 0; | ||
11007 | icmd->un.xseq64.bdl.bdeSize = 0; | ||
11008 | icmd->un.xseq64.w5.hcsw.Dfctl = 0; | ||
11009 | icmd->un.xseq64.w5.hcsw.Rctl = FC_RCTL_BA_ACC; | ||
11010 | icmd->un.xseq64.w5.hcsw.Type = FC_TYPE_BLS; | ||
11011 | |||
11012 | /* Fill in the rest of iocb fields */ | ||
11013 | icmd->ulpCommand = CMD_XMIT_BLS_RSP64_CX; | ||
11014 | icmd->ulpBdeCount = 0; | ||
11015 | icmd->ulpLe = 1; | ||
11016 | icmd->ulpClass = CLASS3; | ||
11017 | icmd->ulpContext = ndlp->nlp_rpi; | ||
11018 | icmd->un.ulpWord[3] = oxid; | ||
11019 | |||
11020 | ctiocb->sli4_xritag = NO_XRI; | ||
11021 | ctiocb->iocb_cmpl = NULL; | ||
11022 | ctiocb->vport = phba->pport; | ||
11023 | ctiocb->iocb_cmpl = lpfc_sli4_seq_abort_acc_cmpl; | ||
11024 | |||
11025 | /* Xmit CT abts accept on exchange <xid> */ | ||
11026 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | ||
11027 | "1200 Xmit CT ABTS ACC on exchange x%x Data: x%x\n", | ||
11028 | CMD_XMIT_BLS_RSP64_CX, phba->link_state); | ||
11029 | lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, ctiocb, 0); | ||
11030 | } | ||
11031 | |||
11032 | /** | ||
11033 | * lpfc_sli4_handle_unsol_abort - Handle sli-4 unsolicited abort event | ||
11034 | * @vport: Pointer to the vport on which this sequence was received | ||
11035 | * @dmabuf: pointer to a dmabuf that describes the FC sequence | ||
11036 | * | ||
11037 | * This function handles an SLI-4 unsolicited abort event. If the unsolicited | ||
11038 | * receive sequence is only partially assembed by the driver, it shall abort | ||
11039 | * the partially assembled frames for the sequence. Otherwise, if the | ||
11040 | * unsolicited receive sequence has been completely assembled and passed to | ||
11041 | * the Upper Layer Protocol (UPL), it then mark the per oxid status for the | ||
11042 | * unsolicited sequence has been aborted. After that, it will issue a basic | ||
11043 | * accept to accept the abort. | ||
11044 | **/ | ||
11045 | void | ||
11046 | lpfc_sli4_handle_unsol_abort(struct lpfc_vport *vport, | ||
11047 | struct hbq_dmabuf *dmabuf) | ||
11048 | { | ||
11049 | struct lpfc_hba *phba = vport->phba; | ||
11050 | struct fc_frame_header fc_hdr; | ||
11051 | bool abts_par; | ||
11052 | |||
11053 | /* Try to abort partially assembled seq */ | ||
11054 | abts_par = lpfc_sli4_abort_partial_seq(vport, dmabuf); | ||
11055 | |||
11056 | /* Make a copy of fc_hdr before the dmabuf being released */ | ||
11057 | memcpy(&fc_hdr, dmabuf->hbuf.virt, sizeof(struct fc_frame_header)); | ||
11058 | |||
11059 | /* Send abort to ULP if partially seq abort failed */ | ||
11060 | if (abts_par == false) | ||
11061 | lpfc_sli4_send_seq_to_ulp(vport, dmabuf); | ||
11062 | else | ||
11063 | lpfc_in_buf_free(phba, &dmabuf->dbuf); | ||
11064 | /* Send basic accept (BA_ACC) to the abort requester */ | ||
11065 | lpfc_sli4_seq_abort_acc(phba, &fc_hdr); | ||
11066 | } | ||
11067 | |||
11068 | /** | ||
10873 | * lpfc_seq_complete - Indicates if a sequence is complete | 11069 | * lpfc_seq_complete - Indicates if a sequence is complete |
10874 | * @dmabuf: pointer to a dmabuf that describes the FC sequence | 11070 | * @dmabuf: pointer to a dmabuf that describes the FC sequence |
10875 | * | 11071 | * |
@@ -10941,9 +11137,7 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf) | |||
10941 | /* remove from receive buffer list */ | 11137 | /* remove from receive buffer list */ |
10942 | list_del_init(&seq_dmabuf->hbuf.list); | 11138 | list_del_init(&seq_dmabuf->hbuf.list); |
10943 | /* get the Remote Port's SID */ | 11139 | /* get the Remote Port's SID */ |
10944 | sid = (fc_hdr->fh_s_id[0] << 16 | | 11140 | sid = sli4_sid_from_fc_hdr(fc_hdr); |
10945 | fc_hdr->fh_s_id[1] << 8 | | ||
10946 | fc_hdr->fh_s_id[2]); | ||
10947 | /* Get an iocbq struct to fill in. */ | 11141 | /* Get an iocbq struct to fill in. */ |
10948 | first_iocbq = lpfc_sli_get_iocbq(vport->phba); | 11142 | first_iocbq = lpfc_sli_get_iocbq(vport->phba); |
10949 | if (first_iocbq) { | 11143 | if (first_iocbq) { |
@@ -11010,6 +11204,43 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf) | |||
11010 | return first_iocbq; | 11204 | return first_iocbq; |
11011 | } | 11205 | } |
11012 | 11206 | ||
11207 | static void | ||
11208 | lpfc_sli4_send_seq_to_ulp(struct lpfc_vport *vport, | ||
11209 | struct hbq_dmabuf *seq_dmabuf) | ||
11210 | { | ||
11211 | struct fc_frame_header *fc_hdr; | ||
11212 | struct lpfc_iocbq *iocbq, *curr_iocb, *next_iocb; | ||
11213 | struct lpfc_hba *phba = vport->phba; | ||
11214 | |||
11215 | fc_hdr = (struct fc_frame_header *)seq_dmabuf->hbuf.virt; | ||
11216 | iocbq = lpfc_prep_seq(vport, seq_dmabuf); | ||
11217 | if (!iocbq) { | ||
11218 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | ||
11219 | "2707 Ring %d handler: Failed to allocate " | ||
11220 | "iocb Rctl x%x Type x%x received\n", | ||
11221 | LPFC_ELS_RING, | ||
11222 | fc_hdr->fh_r_ctl, fc_hdr->fh_type); | ||
11223 | return; | ||
11224 | } | ||
11225 | if (!lpfc_complete_unsol_iocb(phba, | ||
11226 | &phba->sli.ring[LPFC_ELS_RING], | ||
11227 | iocbq, fc_hdr->fh_r_ctl, | ||
11228 | fc_hdr->fh_type)) | ||
11229 | lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, | ||
11230 | "2540 Ring %d handler: unexpected Rctl " | ||
11231 | "x%x Type x%x received\n", | ||
11232 | LPFC_ELS_RING, | ||
11233 | fc_hdr->fh_r_ctl, fc_hdr->fh_type); | ||
11234 | |||
11235 | /* Free iocb created in lpfc_prep_seq */ | ||
11236 | list_for_each_entry_safe(curr_iocb, next_iocb, | ||
11237 | &iocbq->list, list) { | ||
11238 | list_del_init(&curr_iocb->list); | ||
11239 | lpfc_sli_release_iocbq(phba, curr_iocb); | ||
11240 | } | ||
11241 | lpfc_sli_release_iocbq(phba, iocbq); | ||
11242 | } | ||
11243 | |||
11013 | /** | 11244 | /** |
11014 | * lpfc_sli4_handle_received_buffer - Handle received buffers from firmware | 11245 | * lpfc_sli4_handle_received_buffer - Handle received buffers from firmware |
11015 | * @phba: Pointer to HBA context object. | 11246 | * @phba: Pointer to HBA context object. |
@@ -11030,7 +11261,6 @@ lpfc_sli4_handle_received_buffer(struct lpfc_hba *phba, | |||
11030 | struct fc_frame_header *fc_hdr; | 11261 | struct fc_frame_header *fc_hdr; |
11031 | struct lpfc_vport *vport; | 11262 | struct lpfc_vport *vport; |
11032 | uint32_t fcfi; | 11263 | uint32_t fcfi; |
11033 | struct lpfc_iocbq *iocbq; | ||
11034 | 11264 | ||
11035 | /* Clear hba flag and get all received buffers into the cmplq */ | 11265 | /* Clear hba flag and get all received buffers into the cmplq */ |
11036 | spin_lock_irq(&phba->hbalock); | 11266 | spin_lock_irq(&phba->hbalock); |
@@ -11051,6 +11281,12 @@ lpfc_sli4_handle_received_buffer(struct lpfc_hba *phba, | |||
11051 | lpfc_in_buf_free(phba, &dmabuf->dbuf); | 11281 | lpfc_in_buf_free(phba, &dmabuf->dbuf); |
11052 | return; | 11282 | return; |
11053 | } | 11283 | } |
11284 | /* Handle the basic abort sequence (BA_ABTS) event */ | ||
11285 | if (fc_hdr->fh_r_ctl == FC_RCTL_BA_ABTS) { | ||
11286 | lpfc_sli4_handle_unsol_abort(vport, dmabuf); | ||
11287 | return; | ||
11288 | } | ||
11289 | |||
11054 | /* Link this frame */ | 11290 | /* Link this frame */ |
11055 | seq_dmabuf = lpfc_fc_frame_add(vport, dmabuf); | 11291 | seq_dmabuf = lpfc_fc_frame_add(vport, dmabuf); |
11056 | if (!seq_dmabuf) { | 11292 | if (!seq_dmabuf) { |
@@ -11068,17 +11304,8 @@ lpfc_sli4_handle_received_buffer(struct lpfc_hba *phba, | |||
11068 | dmabuf->tag = -1; | 11304 | dmabuf->tag = -1; |
11069 | return; | 11305 | return; |
11070 | } | 11306 | } |
11071 | fc_hdr = (struct fc_frame_header *)seq_dmabuf->hbuf.virt; | 11307 | /* Send the complete sequence to the upper layer protocol */ |
11072 | iocbq = lpfc_prep_seq(vport, seq_dmabuf); | 11308 | lpfc_sli4_send_seq_to_ulp(vport, seq_dmabuf); |
11073 | if (!lpfc_complete_unsol_iocb(phba, | ||
11074 | &phba->sli.ring[LPFC_ELS_RING], | ||
11075 | iocbq, fc_hdr->fh_r_ctl, | ||
11076 | fc_hdr->fh_type)) | ||
11077 | lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, | ||
11078 | "2540 Ring %d handler: unexpected Rctl " | ||
11079 | "x%x Type x%x received\n", | ||
11080 | LPFC_ELS_RING, | ||
11081 | fc_hdr->fh_r_ctl, fc_hdr->fh_type); | ||
11082 | } | 11309 | } |
11083 | 11310 | ||
11084 | /** | 11311 | /** |