aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_sli.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_sli.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c267
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);
60static int lpfc_sli4_read_rev(struct lpfc_hba *, LPFC_MBOXQ_t *, 60static int lpfc_sli4_read_rev(struct lpfc_hba *, LPFC_MBOXQ_t *,
61 uint8_t *, uint32_t *); 61 uint8_t *, uint32_t *);
62 62static void lpfc_sli4_send_seq_to_ulp(struct lpfc_vport *,
63 struct hbq_dmabuf *);
63static IOCB_t * 64static IOCB_t *
64lpfc_get_iocb_from_iocbq(struct lpfc_iocbq *iocbq) 65lpfc_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 **/
10913static bool
10914lpfc_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 **/
10959static void
10960lpfc_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 **/
10976static void
10977lpfc_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 **/
11045void
11046lpfc_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
11207static void
11208lpfc_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/**