diff options
author | James Smart <james.smart@emulex.com> | 2010-01-26 23:07:37 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-02-08 19:37:53 -0500 |
commit | 341af10239c4c87192bf762f53c7bcb1f3a1e767 (patch) | |
tree | 41f7dfa01fc753e7873239daf9155765d153d776 /drivers/scsi/lpfc/lpfc_sli.c | |
parent | 2cec802980727f1daa46d8c31b411e083d49d7a2 (diff) |
[SCSI] lpfc 8.3.8: BugFixes: SLI relates changes
Fix hardware/SLI relates issues:
- Handle XB bit so that ELS XRIs are not prematurely released.
- Handle XB bit so that FCP XRIs are not prematurely released.
- Define new security SLI Commands.
- Remove unused security SLI commands
- Skip receive data size parameter check on received FLOGI.
- Added LPFC_USE_FCPWQIDX flag to iocb to force SLI layer
to submit abort WQE on same WQ as the command WQE.
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 | 112 |
1 files changed, 91 insertions, 21 deletions
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 589549b2bf0e..dc7c5c1231df 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -580,10 +580,7 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) | |||
580 | else | 580 | else |
581 | sglq = __lpfc_clear_active_sglq(phba, iocbq->sli4_xritag); | 581 | sglq = __lpfc_clear_active_sglq(phba, iocbq->sli4_xritag); |
582 | if (sglq) { | 582 | if (sglq) { |
583 | if (iocbq->iocb_flag & LPFC_DRIVER_ABORTED | 583 | if (iocbq->iocb_flag & LPFC_EXCHANGE_BUSY) { |
584 | && ((iocbq->iocb.ulpStatus == IOSTAT_LOCAL_REJECT) | ||
585 | && (iocbq->iocb.un.ulpWord[4] | ||
586 | == IOERR_ABORT_REQUESTED))) { | ||
587 | spin_lock_irqsave(&phba->sli4_hba.abts_sgl_list_lock, | 584 | spin_lock_irqsave(&phba->sli4_hba.abts_sgl_list_lock, |
588 | iflag); | 585 | iflag); |
589 | list_add(&sglq->list, | 586 | list_add(&sglq->list, |
@@ -764,10 +761,6 @@ lpfc_sli_iocb_cmd_type(uint8_t iocb_cmnd) | |||
764 | case DSSCMD_IWRITE64_CX: | 761 | case DSSCMD_IWRITE64_CX: |
765 | case DSSCMD_IREAD64_CR: | 762 | case DSSCMD_IREAD64_CR: |
766 | case DSSCMD_IREAD64_CX: | 763 | case DSSCMD_IREAD64_CX: |
767 | case DSSCMD_INVALIDATE_DEK: | ||
768 | case DSSCMD_SET_KEK: | ||
769 | case DSSCMD_GET_KEK_ID: | ||
770 | case DSSCMD_GEN_XFER: | ||
771 | type = LPFC_SOL_IOCB; | 764 | type = LPFC_SOL_IOCB; |
772 | break; | 765 | break; |
773 | case CMD_ABORT_XRI_CN: | 766 | case CMD_ABORT_XRI_CN: |
@@ -2228,9 +2221,15 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
2228 | * All other are passed to the completion callback. | 2221 | * All other are passed to the completion callback. |
2229 | */ | 2222 | */ |
2230 | if (pring->ringno == LPFC_ELS_RING) { | 2223 | if (pring->ringno == LPFC_ELS_RING) { |
2231 | if (cmdiocbp->iocb_flag & LPFC_DRIVER_ABORTED) { | 2224 | if ((phba->sli_rev < LPFC_SLI_REV4) && |
2225 | (cmdiocbp->iocb_flag & | ||
2226 | LPFC_DRIVER_ABORTED)) { | ||
2227 | spin_lock_irqsave(&phba->hbalock, | ||
2228 | iflag); | ||
2232 | cmdiocbp->iocb_flag &= | 2229 | cmdiocbp->iocb_flag &= |
2233 | ~LPFC_DRIVER_ABORTED; | 2230 | ~LPFC_DRIVER_ABORTED; |
2231 | spin_unlock_irqrestore(&phba->hbalock, | ||
2232 | iflag); | ||
2234 | saveq->iocb.ulpStatus = | 2233 | saveq->iocb.ulpStatus = |
2235 | IOSTAT_LOCAL_REJECT; | 2234 | IOSTAT_LOCAL_REJECT; |
2236 | saveq->iocb.un.ulpWord[4] = | 2235 | saveq->iocb.un.ulpWord[4] = |
@@ -2240,7 +2239,47 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
2240 | * of DMAing payload, so don't free data | 2239 | * of DMAing payload, so don't free data |
2241 | * buffer till after a hbeat. | 2240 | * buffer till after a hbeat. |
2242 | */ | 2241 | */ |
2242 | spin_lock_irqsave(&phba->hbalock, | ||
2243 | iflag); | ||
2243 | saveq->iocb_flag |= LPFC_DELAY_MEM_FREE; | 2244 | saveq->iocb_flag |= LPFC_DELAY_MEM_FREE; |
2245 | spin_unlock_irqrestore(&phba->hbalock, | ||
2246 | iflag); | ||
2247 | } | ||
2248 | if ((phba->sli_rev == LPFC_SLI_REV4) && | ||
2249 | (saveq->iocb_flag & LPFC_EXCHANGE_BUSY)) { | ||
2250 | /* Set cmdiocb flag for the exchange | ||
2251 | * busy so sgl (xri) will not be | ||
2252 | * released until the abort xri is | ||
2253 | * received from hba, clear the | ||
2254 | * LPFC_DRIVER_ABORTED bit in case | ||
2255 | * it was driver initiated abort. | ||
2256 | */ | ||
2257 | spin_lock_irqsave(&phba->hbalock, | ||
2258 | iflag); | ||
2259 | cmdiocbp->iocb_flag &= | ||
2260 | ~LPFC_DRIVER_ABORTED; | ||
2261 | cmdiocbp->iocb_flag |= | ||
2262 | LPFC_EXCHANGE_BUSY; | ||
2263 | spin_unlock_irqrestore(&phba->hbalock, | ||
2264 | iflag); | ||
2265 | cmdiocbp->iocb.ulpStatus = | ||
2266 | IOSTAT_LOCAL_REJECT; | ||
2267 | cmdiocbp->iocb.un.ulpWord[4] = | ||
2268 | IOERR_ABORT_REQUESTED; | ||
2269 | /* | ||
2270 | * For SLI4, irsiocb contains NO_XRI | ||
2271 | * in sli_xritag, it shall not affect | ||
2272 | * releasing sgl (xri) process. | ||
2273 | */ | ||
2274 | saveq->iocb.ulpStatus = | ||
2275 | IOSTAT_LOCAL_REJECT; | ||
2276 | saveq->iocb.un.ulpWord[4] = | ||
2277 | IOERR_SLI_ABORTED; | ||
2278 | spin_lock_irqsave(&phba->hbalock, | ||
2279 | iflag); | ||
2280 | saveq->iocb_flag |= LPFC_DELAY_MEM_FREE; | ||
2281 | spin_unlock_irqrestore(&phba->hbalock, | ||
2282 | iflag); | ||
2244 | } | 2283 | } |
2245 | } | 2284 | } |
2246 | (cmdiocbp->iocb_cmpl) (phba, cmdiocbp, saveq); | 2285 | (cmdiocbp->iocb_cmpl) (phba, cmdiocbp, saveq); |
@@ -5987,12 +6026,10 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, | |||
5987 | else | 6026 | else |
5988 | bf_set(abort_cmd_ia, &wqe->abort_cmd, 0); | 6027 | bf_set(abort_cmd_ia, &wqe->abort_cmd, 0); |
5989 | bf_set(abort_cmd_criteria, &wqe->abort_cmd, T_XRI_TAG); | 6028 | bf_set(abort_cmd_criteria, &wqe->abort_cmd, T_XRI_TAG); |
5990 | abort_tag = iocbq->iocb.un.acxri.abortIoTag; | ||
5991 | wqe->words[5] = 0; | 6029 | wqe->words[5] = 0; |
5992 | bf_set(lpfc_wqe_gen_ct, &wqe->generic, | 6030 | bf_set(lpfc_wqe_gen_ct, &wqe->generic, |
5993 | ((iocbq->iocb.ulpCt_h << 1) | iocbq->iocb.ulpCt_l)); | 6031 | ((iocbq->iocb.ulpCt_h << 1) | iocbq->iocb.ulpCt_l)); |
5994 | abort_tag = iocbq->iocb.un.acxri.abortIoTag; | 6032 | abort_tag = iocbq->iocb.un.acxri.abortIoTag; |
5995 | wqe->generic.abort_tag = abort_tag; | ||
5996 | /* | 6033 | /* |
5997 | * The abort handler will send us CMD_ABORT_XRI_CN or | 6034 | * The abort handler will send us CMD_ABORT_XRI_CN or |
5998 | * CMD_CLOSE_XRI_CN and the fw only accepts CMD_ABORT_XRI_CX | 6035 | * CMD_CLOSE_XRI_CN and the fw only accepts CMD_ABORT_XRI_CX |
@@ -6121,15 +6158,15 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, | |||
6121 | if (lpfc_sli4_iocb2wqe(phba, piocb, &wqe)) | 6158 | if (lpfc_sli4_iocb2wqe(phba, piocb, &wqe)) |
6122 | return IOCB_ERROR; | 6159 | return IOCB_ERROR; |
6123 | 6160 | ||
6124 | if (piocb->iocb_flag & LPFC_IO_FCP) { | 6161 | if ((piocb->iocb_flag & LPFC_IO_FCP) || |
6162 | (piocb->iocb_flag & LPFC_USE_FCPWQIDX)) { | ||
6125 | /* | 6163 | /* |
6126 | * For FCP command IOCB, get a new WQ index to distribute | 6164 | * For FCP command IOCB, get a new WQ index to distribute |
6127 | * WQE across the WQsr. On the other hand, for abort IOCB, | 6165 | * WQE across the WQsr. On the other hand, for abort IOCB, |
6128 | * it carries the same WQ index to the original command | 6166 | * it carries the same WQ index to the original command |
6129 | * IOCB. | 6167 | * IOCB. |
6130 | */ | 6168 | */ |
6131 | if ((piocb->iocb.ulpCommand != CMD_ABORT_XRI_CN) && | 6169 | if (piocb->iocb_flag & LPFC_IO_FCP) |
6132 | (piocb->iocb.ulpCommand != CMD_CLOSE_XRI_CN)) | ||
6133 | piocb->fcp_wqidx = lpfc_sli4_scmd_to_wqidx_distr(phba); | 6170 | piocb->fcp_wqidx = lpfc_sli4_scmd_to_wqidx_distr(phba); |
6134 | if (lpfc_sli4_wq_put(phba->sli4_hba.fcp_wq[piocb->fcp_wqidx], | 6171 | if (lpfc_sli4_wq_put(phba->sli4_hba.fcp_wq[piocb->fcp_wqidx], |
6135 | &wqe)) | 6172 | &wqe)) |
@@ -7004,7 +7041,14 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
7004 | abort_iocb->iocb.ulpContext != abort_context || | 7041 | abort_iocb->iocb.ulpContext != abort_context || |
7005 | (abort_iocb->iocb_flag & LPFC_DRIVER_ABORTED) == 0) | 7042 | (abort_iocb->iocb_flag & LPFC_DRIVER_ABORTED) == 0) |
7006 | spin_unlock_irq(&phba->hbalock); | 7043 | spin_unlock_irq(&phba->hbalock); |
7007 | else { | 7044 | else if (phba->sli_rev < LPFC_SLI_REV4) { |
7045 | /* | ||
7046 | * leave the SLI4 aborted command on the txcmplq | ||
7047 | * list and the command complete WCQE's XB bit | ||
7048 | * will tell whether the SGL (XRI) can be released | ||
7049 | * immediately or to the aborted SGL list for the | ||
7050 | * following abort XRI from the HBA. | ||
7051 | */ | ||
7008 | list_del_init(&abort_iocb->list); | 7052 | list_del_init(&abort_iocb->list); |
7009 | pring->txcmplq_cnt--; | 7053 | pring->txcmplq_cnt--; |
7010 | spin_unlock_irq(&phba->hbalock); | 7054 | spin_unlock_irq(&phba->hbalock); |
@@ -7013,11 +7057,13 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
7013 | * payload, so don't free data buffer till after | 7057 | * payload, so don't free data buffer till after |
7014 | * a hbeat. | 7058 | * a hbeat. |
7015 | */ | 7059 | */ |
7060 | spin_lock_irq(&phba->hbalock); | ||
7016 | abort_iocb->iocb_flag |= LPFC_DELAY_MEM_FREE; | 7061 | abort_iocb->iocb_flag |= LPFC_DELAY_MEM_FREE; |
7017 | |||
7018 | abort_iocb->iocb_flag &= ~LPFC_DRIVER_ABORTED; | 7062 | abort_iocb->iocb_flag &= ~LPFC_DRIVER_ABORTED; |
7063 | spin_unlock_irq(&phba->hbalock); | ||
7064 | |||
7019 | abort_iocb->iocb.ulpStatus = IOSTAT_LOCAL_REJECT; | 7065 | abort_iocb->iocb.ulpStatus = IOSTAT_LOCAL_REJECT; |
7020 | abort_iocb->iocb.un.ulpWord[4] = IOERR_SLI_ABORTED; | 7066 | abort_iocb->iocb.un.ulpWord[4] = IOERR_ABORT_REQUESTED; |
7021 | (abort_iocb->iocb_cmpl)(phba, abort_iocb, abort_iocb); | 7067 | (abort_iocb->iocb_cmpl)(phba, abort_iocb, abort_iocb); |
7022 | } | 7068 | } |
7023 | } | 7069 | } |
@@ -7106,7 +7152,7 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
7106 | return 0; | 7152 | return 0; |
7107 | 7153 | ||
7108 | /* This signals the response to set the correct status | 7154 | /* This signals the response to set the correct status |
7109 | * before calling the completion handler. | 7155 | * before calling the completion handler |
7110 | */ | 7156 | */ |
7111 | cmdiocb->iocb_flag |= LPFC_DRIVER_ABORTED; | 7157 | cmdiocb->iocb_flag |= LPFC_DRIVER_ABORTED; |
7112 | 7158 | ||
@@ -7124,6 +7170,8 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
7124 | 7170 | ||
7125 | /* ABTS WQE must go to the same WQ as the WQE to be aborted */ | 7171 | /* ABTS WQE must go to the same WQ as the WQE to be aborted */ |
7126 | abtsiocbp->fcp_wqidx = cmdiocb->fcp_wqidx; | 7172 | abtsiocbp->fcp_wqidx = cmdiocb->fcp_wqidx; |
7173 | if (cmdiocb->iocb_flag & LPFC_IO_FCP) | ||
7174 | abtsiocbp->iocb_flag |= LPFC_USE_FCPWQIDX; | ||
7127 | 7175 | ||
7128 | if (phba->link_state >= LPFC_LINK_UP) | 7176 | if (phba->link_state >= LPFC_LINK_UP) |
7129 | iabt->ulpCommand = CMD_ABORT_XRI_CN; | 7177 | iabt->ulpCommand = CMD_ABORT_XRI_CN; |
@@ -7330,6 +7378,8 @@ lpfc_sli_abort_iocb(struct lpfc_vport *vport, struct lpfc_sli_ring *pring, | |||
7330 | 7378 | ||
7331 | /* ABTS WQE must go to the same WQ as the WQE to be aborted */ | 7379 | /* ABTS WQE must go to the same WQ as the WQE to be aborted */ |
7332 | abtsiocb->fcp_wqidx = iocbq->fcp_wqidx; | 7380 | abtsiocb->fcp_wqidx = iocbq->fcp_wqidx; |
7381 | if (iocbq->iocb_flag & LPFC_IO_FCP) | ||
7382 | abtsiocb->iocb_flag |= LPFC_USE_FCPWQIDX; | ||
7333 | 7383 | ||
7334 | if (lpfc_is_link_up(phba)) | 7384 | if (lpfc_is_link_up(phba)) |
7335 | abtsiocb->iocb.ulpCommand = CMD_ABORT_XRI_CN; | 7385 | abtsiocb->iocb.ulpCommand = CMD_ABORT_XRI_CN; |
@@ -8359,11 +8409,24 @@ void lpfc_sli4_els_xri_abort_event_proc(struct lpfc_hba *phba) | |||
8359 | } | 8409 | } |
8360 | } | 8410 | } |
8361 | 8411 | ||
8412 | /** | ||
8413 | * lpfc_sli4_iocb_param_transfer - Transfer pIocbOut and cmpl status to pIocbIn | ||
8414 | * @phba: pointer to lpfc hba data structure | ||
8415 | * @pIocbIn: pointer to the rspiocbq | ||
8416 | * @pIocbOut: pointer to the cmdiocbq | ||
8417 | * @wcqe: pointer to the complete wcqe | ||
8418 | * | ||
8419 | * This routine transfers the fields of a command iocbq to a response iocbq | ||
8420 | * by copying all the IOCB fields from command iocbq and transferring the | ||
8421 | * completion status information from the complete wcqe. | ||
8422 | **/ | ||
8362 | static void | 8423 | static void |
8363 | lpfc_sli4_iocb_param_transfer(struct lpfc_iocbq *pIocbIn, | 8424 | lpfc_sli4_iocb_param_transfer(struct lpfc_hba *phba, |
8425 | struct lpfc_iocbq *pIocbIn, | ||
8364 | struct lpfc_iocbq *pIocbOut, | 8426 | struct lpfc_iocbq *pIocbOut, |
8365 | struct lpfc_wcqe_complete *wcqe) | 8427 | struct lpfc_wcqe_complete *wcqe) |
8366 | { | 8428 | { |
8429 | unsigned long iflags; | ||
8367 | size_t offset = offsetof(struct lpfc_iocbq, iocb); | 8430 | size_t offset = offsetof(struct lpfc_iocbq, iocb); |
8368 | 8431 | ||
8369 | memcpy((char *)pIocbIn + offset, (char *)pIocbOut + offset, | 8432 | memcpy((char *)pIocbIn + offset, (char *)pIocbOut + offset, |
@@ -8379,6 +8442,13 @@ lpfc_sli4_iocb_param_transfer(struct lpfc_iocbq *pIocbIn, | |||
8379 | pIocbIn->iocb.un.ulpWord[4] = wcqe->parameter; | 8442 | pIocbIn->iocb.un.ulpWord[4] = wcqe->parameter; |
8380 | else | 8443 | else |
8381 | pIocbIn->iocb.un.ulpWord[4] = wcqe->parameter; | 8444 | pIocbIn->iocb.un.ulpWord[4] = wcqe->parameter; |
8445 | |||
8446 | /* Pick up HBA exchange busy condition */ | ||
8447 | if (bf_get(lpfc_wcqe_c_xb, wcqe)) { | ||
8448 | spin_lock_irqsave(&phba->hbalock, iflags); | ||
8449 | pIocbIn->iocb_flag |= LPFC_EXCHANGE_BUSY; | ||
8450 | spin_unlock_irqrestore(&phba->hbalock, iflags); | ||
8451 | } | ||
8382 | } | 8452 | } |
8383 | 8453 | ||
8384 | /** | 8454 | /** |
@@ -8419,7 +8489,7 @@ lpfc_sli4_els_wcqe_to_rspiocbq(struct lpfc_hba *phba, | |||
8419 | } | 8489 | } |
8420 | 8490 | ||
8421 | /* Fake the irspiocbq and copy necessary response information */ | 8491 | /* Fake the irspiocbq and copy necessary response information */ |
8422 | lpfc_sli4_iocb_param_transfer(irspiocbq, cmdiocbq, wcqe); | 8492 | lpfc_sli4_iocb_param_transfer(phba, irspiocbq, cmdiocbq, wcqe); |
8423 | 8493 | ||
8424 | return irspiocbq; | 8494 | return irspiocbq; |
8425 | } | 8495 | } |
@@ -8976,7 +9046,7 @@ lpfc_sli4_fp_handle_fcp_wcqe(struct lpfc_hba *phba, | |||
8976 | } | 9046 | } |
8977 | 9047 | ||
8978 | /* Fake the irspiocb and copy necessary response information */ | 9048 | /* Fake the irspiocb and copy necessary response information */ |
8979 | lpfc_sli4_iocb_param_transfer(&irspiocbq, cmdiocbq, wcqe); | 9049 | lpfc_sli4_iocb_param_transfer(phba, &irspiocbq, cmdiocbq, wcqe); |
8980 | 9050 | ||
8981 | /* Pass the cmd_iocb and the rsp state to the upper layer */ | 9051 | /* Pass the cmd_iocb and the rsp state to the upper layer */ |
8982 | (cmdiocbq->iocb_cmpl)(phba, cmdiocbq, &irspiocbq); | 9052 | (cmdiocbq->iocb_cmpl)(phba, cmdiocbq, &irspiocbq); |