diff options
author | James Smart <James.Smart@Emulex.Com> | 2009-11-18 15:39:44 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2009-12-04 13:01:51 -0500 |
commit | 5ffc266ee7a62741ebee89ede15049ec0f02fa75 (patch) | |
tree | 1ffd531c5b95d3e0c2bf0d905d34f497827ff0ee /drivers | |
parent | c868595d5686e97183bc1ad85502835d81d7a457 (diff) |
[SCSI] lpfc 8.3.6 : FC Protocol Fixes
FC protocol fixes.
- Fix send sequence logic to handle multi SGL IOCBs.
- Fix FDISC completion always setting VPORT state to failed.
- Ported the fix on reporting of max_vpi to uppper layer.
- Fix incorrect number of Vports allowed to be created.
- Fixed Dead FCoE port after creating vports.
- Added handling of ELS request for Reinstate Recovery Qualifier (RRQ)
- Handle unsolicited CT exchange initiator receiving CT exchange ABTS
- Migrate LUN queue depth ramp up code to scsi mid-layer.
- Made ABTS WQE go to the same WQ as the WQE to be aborted.
- Fix Vport does not rediscover after FCF goes away.
- Fixed lpfc_unreg_vfi failure after devloss timeout.
- Fixed RPI bit leak.
- Fix hbq pointer corruption during target discovery.
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_disc.h | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 40 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hw.h | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hw4.h | 23 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 3 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nportdisc.c | 7 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 135 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 133 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.h | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli4.h | 5 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_vport.c | 2 |
12 files changed, 235 insertions, 119 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 2fd3e45c577e..1cc23a69db5e 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
@@ -202,6 +202,7 @@ struct lpfc_stats { | |||
202 | uint32_t elsRcvLIRR; | 202 | uint32_t elsRcvLIRR; |
203 | uint32_t elsRcvRPS; | 203 | uint32_t elsRcvRPS; |
204 | uint32_t elsRcvRPL; | 204 | uint32_t elsRcvRPL; |
205 | uint32_t elsRcvRRQ; | ||
205 | uint32_t elsXmitFLOGI; | 206 | uint32_t elsXmitFLOGI; |
206 | uint32_t elsXmitFDISC; | 207 | uint32_t elsXmitFDISC; |
207 | uint32_t elsXmitPLOGI; | 208 | uint32_t elsXmitPLOGI; |
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h index f26f6e160a2a..2851d75ffc6f 100644 --- a/drivers/scsi/lpfc/lpfc_disc.h +++ b/drivers/scsi/lpfc/lpfc_disc.h | |||
@@ -105,8 +105,6 @@ struct lpfc_nodelist { | |||
105 | struct lpfc_vport *vport; | 105 | struct lpfc_vport *vport; |
106 | struct lpfc_work_evt els_retry_evt; | 106 | struct lpfc_work_evt els_retry_evt; |
107 | struct lpfc_work_evt dev_loss_evt; | 107 | struct lpfc_work_evt dev_loss_evt; |
108 | unsigned long last_ramp_up_time; /* jiffy of last ramp up */ | ||
109 | unsigned long last_q_full_time; /* jiffy of last queue full */ | ||
110 | struct kref kref; | 108 | struct kref kref; |
111 | atomic_t cmd_pending; | 109 | atomic_t cmd_pending; |
112 | uint32_t cmd_qdepth; | 110 | uint32_t cmd_qdepth; |
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index e9e423f28f8a..a079bbc03cf8 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -4521,6 +4521,29 @@ lpfc_els_rcv_lirr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
4521 | } | 4521 | } |
4522 | 4522 | ||
4523 | /** | 4523 | /** |
4524 | * lpfc_els_rcv_rrq - Process an unsolicited rrq iocb | ||
4525 | * @vport: pointer to a host virtual N_Port data structure. | ||
4526 | * @cmdiocb: pointer to lpfc command iocb data structure. | ||
4527 | * @ndlp: pointer to a node-list data structure. | ||
4528 | * | ||
4529 | * This routine processes a Reinstate Recovery Qualifier (RRQ) IOCB | ||
4530 | * received as an ELS unsolicited event. A request to RRQ shall only | ||
4531 | * be accepted if the Originator Nx_Port N_Port_ID or the Responder | ||
4532 | * Nx_Port N_Port_ID of the target Exchange is the same as the | ||
4533 | * N_Port_ID of the Nx_Port that makes the request. If the RRQ is | ||
4534 | * not accepted, an LS_RJT with reason code "Unable to perform | ||
4535 | * command request" and reason code explanation "Invalid Originator | ||
4536 | * S_ID" shall be returned. For now, we just unconditionally accept | ||
4537 | * RRQ from the target. | ||
4538 | **/ | ||
4539 | static void | ||
4540 | lpfc_els_rcv_rrq(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | ||
4541 | struct lpfc_nodelist *ndlp) | ||
4542 | { | ||
4543 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); | ||
4544 | } | ||
4545 | |||
4546 | /** | ||
4524 | * lpfc_els_rsp_rps_acc - Completion callbk func for MBX_READ_LNK_STAT mbox cmd | 4547 | * lpfc_els_rsp_rps_acc - Completion callbk func for MBX_READ_LNK_STAT mbox cmd |
4525 | * @phba: pointer to lpfc hba data structure. | 4548 | * @phba: pointer to lpfc hba data structure. |
4526 | * @pmb: pointer to the driver internal queue element for mailbox command. | 4549 | * @pmb: pointer to the driver internal queue element for mailbox command. |
@@ -5636,6 +5659,16 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
5636 | if (newnode) | 5659 | if (newnode) |
5637 | lpfc_nlp_put(ndlp); | 5660 | lpfc_nlp_put(ndlp); |
5638 | break; | 5661 | break; |
5662 | case ELS_CMD_RRQ: | ||
5663 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, | ||
5664 | "RCV RRQ: did:x%x/ste:x%x flg:x%x", | ||
5665 | did, vport->port_state, ndlp->nlp_flag); | ||
5666 | |||
5667 | phba->fc_stat.elsRcvRRQ++; | ||
5668 | lpfc_els_rcv_rrq(vport, elsiocb, ndlp); | ||
5669 | if (newnode) | ||
5670 | lpfc_nlp_put(ndlp); | ||
5671 | break; | ||
5639 | default: | 5672 | default: |
5640 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, | 5673 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, |
5641 | "RCV ELS cmd: cmd:x%x did:x%x/ste:x%x", | 5674 | "RCV ELS cmd: cmd:x%x did:x%x/ste:x%x", |
@@ -6042,11 +6075,6 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
6042 | irsp->ulpStatus, irsp->un.ulpWord[4]); | 6075 | irsp->ulpStatus, irsp->un.ulpWord[4]); |
6043 | goto fdisc_failed; | 6076 | goto fdisc_failed; |
6044 | } | 6077 | } |
6045 | if (vport->fc_vport->vport_state == FC_VPORT_INITIALIZING) | ||
6046 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); | ||
6047 | lpfc_nlp_put(ndlp); | ||
6048 | /* giving up on FDISC. Cancel discovery timer */ | ||
6049 | lpfc_can_disctmo(vport); | ||
6050 | spin_lock_irq(shost->host_lock); | 6078 | spin_lock_irq(shost->host_lock); |
6051 | vport->fc_flag |= FC_FABRIC; | 6079 | vport->fc_flag |= FC_FABRIC; |
6052 | if (vport->phba->fc_topology == TOPOLOGY_LOOP) | 6080 | if (vport->phba->fc_topology == TOPOLOGY_LOOP) |
@@ -6125,6 +6153,7 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
6125 | int did = ndlp->nlp_DID; | 6153 | int did = ndlp->nlp_DID; |
6126 | int rc; | 6154 | int rc; |
6127 | 6155 | ||
6156 | vport->port_state = LPFC_FDISC; | ||
6128 | cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm)); | 6157 | cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm)); |
6129 | elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, did, | 6158 | elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, did, |
6130 | ELS_CMD_FDISC); | 6159 | ELS_CMD_FDISC); |
@@ -6190,7 +6219,6 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
6190 | return 1; | 6219 | return 1; |
6191 | } | 6220 | } |
6192 | lpfc_vport_set_state(vport, FC_VPORT_INITIALIZING); | 6221 | lpfc_vport_set_state(vport, FC_VPORT_INITIALIZING); |
6193 | vport->port_state = LPFC_FDISC; | ||
6194 | return 0; | 6222 | return 0; |
6195 | } | 6223 | } |
6196 | 6224 | ||
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 7070c77357a9..f279d191b628 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h | |||
@@ -3538,7 +3538,7 @@ typedef struct _IOCB { /* IOCB structure */ | |||
3538 | ASYNCSTAT_FIELDS asyncstat; /* async_status iocb */ | 3538 | ASYNCSTAT_FIELDS asyncstat; /* async_status iocb */ |
3539 | QUE_XRI64_CX_FIELDS quexri64cx; /* que_xri64_cx fields */ | 3539 | QUE_XRI64_CX_FIELDS quexri64cx; /* que_xri64_cx fields */ |
3540 | struct rcv_seq64 rcvseq64; /* RCV_SEQ64 and RCV_CONT64 */ | 3540 | struct rcv_seq64 rcvseq64; /* RCV_SEQ64 and RCV_CONT64 */ |
3541 | 3541 | struct sli4_bls_acc bls_acc; /* UNSOL ABTS BLS_ACC params */ | |
3542 | uint32_t ulpWord[IOCB_WORD_SZ - 2]; /* generic 6 'words' */ | 3542 | uint32_t ulpWord[IOCB_WORD_SZ - 2]; /* generic 6 'words' */ |
3543 | } un; | 3543 | } un; |
3544 | union { | 3544 | union { |
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 95f8b4e0063d..fa3306386786 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h | |||
@@ -194,6 +194,26 @@ struct lpfc_sli4_flags { | |||
194 | #define lpfc_fip_flag_WORD word0 | 194 | #define lpfc_fip_flag_WORD word0 |
195 | }; | 195 | }; |
196 | 196 | ||
197 | struct sli4_bls_acc { | ||
198 | uint32_t word0_rsvd; /* Word0 must be reserved */ | ||
199 | uint32_t word1; | ||
200 | #define lpfc_abts_orig_SHIFT 0 | ||
201 | #define lpfc_abts_orig_MASK 0x00000001 | ||
202 | #define lpfc_abts_orig_WORD word1 | ||
203 | #define LPFC_ABTS_UNSOL_RSP 1 | ||
204 | #define LPFC_ABTS_UNSOL_INT 0 | ||
205 | uint32_t word2; | ||
206 | #define lpfc_abts_rxid_SHIFT 0 | ||
207 | #define lpfc_abts_rxid_MASK 0x0000FFFF | ||
208 | #define lpfc_abts_rxid_WORD word2 | ||
209 | #define lpfc_abts_oxid_SHIFT 16 | ||
210 | #define lpfc_abts_oxid_MASK 0x0000FFFF | ||
211 | #define lpfc_abts_oxid_WORD word2 | ||
212 | uint32_t word3; | ||
213 | uint32_t word4; | ||
214 | uint32_t word5_rsvd; /* Word5 must be reserved */ | ||
215 | }; | ||
216 | |||
197 | /* event queue entry structure */ | 217 | /* event queue entry structure */ |
198 | struct lpfc_eqe { | 218 | struct lpfc_eqe { |
199 | uint32_t word0; | 219 | uint32_t word0; |
@@ -1980,7 +2000,8 @@ struct lpfc_bmbx_create { | |||
1980 | #define SGL_ALIGN_SZ 64 | 2000 | #define SGL_ALIGN_SZ 64 |
1981 | #define SGL_PAGE_SIZE 4096 | 2001 | #define SGL_PAGE_SIZE 4096 |
1982 | /* align SGL addr on a size boundary - adjust address up */ | 2002 | /* align SGL addr on a size boundary - adjust address up */ |
1983 | #define NO_XRI ((uint16_t)-1) | 2003 | #define NO_XRI ((uint16_t)-1) |
2004 | |||
1984 | struct wqe_common { | 2005 | struct wqe_common { |
1985 | uint32_t word6; | 2006 | uint32_t word6; |
1986 | #define wqe_xri_tag_SHIFT 0 | 2007 | #define wqe_xri_tag_SHIFT 0 |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 02268a1eec69..6932657d74ad 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -4931,7 +4931,8 @@ lpfc_sli4_read_config(struct lpfc_hba *phba) | |||
4931 | phba->vpi_base = phba->sli4_hba.max_cfg_param.vpi_base; | 4931 | phba->vpi_base = phba->sli4_hba.max_cfg_param.vpi_base; |
4932 | phba->vfi_base = phba->sli4_hba.max_cfg_param.vfi_base; | 4932 | phba->vfi_base = phba->sli4_hba.max_cfg_param.vfi_base; |
4933 | phba->sli4_hba.next_rpi = phba->sli4_hba.max_cfg_param.rpi_base; | 4933 | phba->sli4_hba.next_rpi = phba->sli4_hba.max_cfg_param.rpi_base; |
4934 | phba->max_vpi = phba->sli4_hba.max_cfg_param.max_vpi; | 4934 | phba->max_vpi = (phba->sli4_hba.max_cfg_param.max_vpi > 0) ? |
4935 | (phba->sli4_hba.max_cfg_param.max_vpi - 1) : 0; | ||
4935 | phba->max_vports = phba->max_vpi; | 4936 | phba->max_vports = phba->max_vpi; |
4936 | lpfc_printf_log(phba, KERN_INFO, LOG_SLI, | 4937 | lpfc_printf_log(phba, KERN_INFO, LOG_SLI, |
4937 | "2003 cfg params XRI(B:%d M:%d), " | 4938 | "2003 cfg params XRI(B:%d M:%d), " |
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 3e74136f1ede..2ed6af194932 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c | |||
@@ -1223,6 +1223,12 @@ lpfc_rcv_logo_reglogin_issue(struct lpfc_vport *vport, | |||
1223 | list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) { | 1223 | list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) { |
1224 | if ((mb->u.mb.mbxCommand == MBX_REG_LOGIN64) && | 1224 | if ((mb->u.mb.mbxCommand == MBX_REG_LOGIN64) && |
1225 | (ndlp == (struct lpfc_nodelist *) mb->context2)) { | 1225 | (ndlp == (struct lpfc_nodelist *) mb->context2)) { |
1226 | if (phba->sli_rev == LPFC_SLI_REV4) { | ||
1227 | spin_unlock_irq(&phba->hbalock); | ||
1228 | lpfc_sli4_free_rpi(phba, | ||
1229 | mb->u.mb.un.varRegLogin.rpi); | ||
1230 | spin_lock_irq(&phba->hbalock); | ||
1231 | } | ||
1226 | mp = (struct lpfc_dmabuf *) (mb->context1); | 1232 | mp = (struct lpfc_dmabuf *) (mb->context1); |
1227 | if (mp) { | 1233 | if (mp) { |
1228 | __lpfc_mbuf_free(phba, mp->virt, mp->phys); | 1234 | __lpfc_mbuf_free(phba, mp->virt, mp->phys); |
@@ -1230,6 +1236,7 @@ lpfc_rcv_logo_reglogin_issue(struct lpfc_vport *vport, | |||
1230 | } | 1236 | } |
1231 | lpfc_nlp_put(ndlp); | 1237 | lpfc_nlp_put(ndlp); |
1232 | list_del(&mb->list); | 1238 | list_del(&mb->list); |
1239 | phba->sli.mboxq_cnt--; | ||
1233 | mempool_free(mb, phba->mbox_mem_pool); | 1240 | mempool_free(mb, phba->mbox_mem_pool); |
1234 | } | 1241 | } |
1235 | } | 1242 | } |
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index f5ab5dd9bbbf..bf80cdefb506 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
@@ -246,6 +246,36 @@ lpfc_send_sdev_queuedepth_change_event(struct lpfc_hba *phba, | |||
246 | } | 246 | } |
247 | 247 | ||
248 | /** | 248 | /** |
249 | * lpfc_change_queue_depth - Alter scsi device queue depth | ||
250 | * @sdev: Pointer the scsi device on which to change the queue depth. | ||
251 | * @qdepth: New queue depth to set the sdev to. | ||
252 | * @reason: The reason for the queue depth change. | ||
253 | * | ||
254 | * This function is called by the midlayer and the LLD to alter the queue | ||
255 | * depth for a scsi device. This function sets the queue depth to the new | ||
256 | * value and sends an event out to log the queue depth change. | ||
257 | **/ | ||
258 | int | ||
259 | lpfc_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason) | ||
260 | { | ||
261 | struct lpfc_vport *vport = (struct lpfc_vport *) sdev->host->hostdata; | ||
262 | struct lpfc_hba *phba = vport->phba; | ||
263 | struct lpfc_rport_data *rdata; | ||
264 | unsigned long new_queue_depth, old_queue_depth; | ||
265 | |||
266 | old_queue_depth = sdev->queue_depth; | ||
267 | scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth); | ||
268 | new_queue_depth = sdev->queue_depth; | ||
269 | rdata = sdev->hostdata; | ||
270 | if (rdata) | ||
271 | lpfc_send_sdev_queuedepth_change_event(phba, vport, | ||
272 | rdata->pnode, sdev->lun, | ||
273 | old_queue_depth, | ||
274 | new_queue_depth); | ||
275 | return sdev->queue_depth; | ||
276 | } | ||
277 | |||
278 | /** | ||
249 | * lpfc_rampdown_queue_depth - Post RAMP_DOWN_QUEUE event to worker thread | 279 | * lpfc_rampdown_queue_depth - Post RAMP_DOWN_QUEUE event to worker thread |
250 | * @phba: The Hba for which this call is being executed. | 280 | * @phba: The Hba for which this call is being executed. |
251 | * | 281 | * |
@@ -309,8 +339,10 @@ lpfc_rampup_queue_depth(struct lpfc_vport *vport, | |||
309 | if (vport->cfg_lun_queue_depth <= queue_depth) | 339 | if (vport->cfg_lun_queue_depth <= queue_depth) |
310 | return; | 340 | return; |
311 | spin_lock_irqsave(&phba->hbalock, flags); | 341 | spin_lock_irqsave(&phba->hbalock, flags); |
312 | if (((phba->last_ramp_up_time + QUEUE_RAMP_UP_INTERVAL) > jiffies) || | 342 | if (time_before(jiffies, |
313 | ((phba->last_rsrc_error_time + QUEUE_RAMP_UP_INTERVAL ) > jiffies)) { | 343 | phba->last_ramp_up_time + QUEUE_RAMP_UP_INTERVAL) || |
344 | time_before(jiffies, | ||
345 | phba->last_rsrc_error_time + QUEUE_RAMP_UP_INTERVAL)) { | ||
314 | spin_unlock_irqrestore(&phba->hbalock, flags); | 346 | spin_unlock_irqrestore(&phba->hbalock, flags); |
315 | return; | 347 | return; |
316 | } | 348 | } |
@@ -342,10 +374,9 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba) | |||
342 | struct lpfc_vport **vports; | 374 | struct lpfc_vport **vports; |
343 | struct Scsi_Host *shost; | 375 | struct Scsi_Host *shost; |
344 | struct scsi_device *sdev; | 376 | struct scsi_device *sdev; |
345 | unsigned long new_queue_depth, old_queue_depth; | 377 | unsigned long new_queue_depth; |
346 | unsigned long num_rsrc_err, num_cmd_success; | 378 | unsigned long num_rsrc_err, num_cmd_success; |
347 | int i; | 379 | int i; |
348 | struct lpfc_rport_data *rdata; | ||
349 | 380 | ||
350 | num_rsrc_err = atomic_read(&phba->num_rsrc_err); | 381 | num_rsrc_err = atomic_read(&phba->num_rsrc_err); |
351 | num_cmd_success = atomic_read(&phba->num_cmd_success); | 382 | num_cmd_success = atomic_read(&phba->num_cmd_success); |
@@ -363,22 +394,8 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba) | |||
363 | else | 394 | else |
364 | new_queue_depth = sdev->queue_depth - | 395 | new_queue_depth = sdev->queue_depth - |
365 | new_queue_depth; | 396 | new_queue_depth; |
366 | old_queue_depth = sdev->queue_depth; | 397 | lpfc_change_queue_depth(sdev, new_queue_depth, |
367 | if (sdev->ordered_tags) | 398 | SCSI_QDEPTH_DEFAULT); |
368 | scsi_adjust_queue_depth(sdev, | ||
369 | MSG_ORDERED_TAG, | ||
370 | new_queue_depth); | ||
371 | else | ||
372 | scsi_adjust_queue_depth(sdev, | ||
373 | MSG_SIMPLE_TAG, | ||
374 | new_queue_depth); | ||
375 | rdata = sdev->hostdata; | ||
376 | if (rdata) | ||
377 | lpfc_send_sdev_queuedepth_change_event( | ||
378 | phba, vports[i], | ||
379 | rdata->pnode, | ||
380 | sdev->lun, old_queue_depth, | ||
381 | new_queue_depth); | ||
382 | } | 399 | } |
383 | } | 400 | } |
384 | lpfc_destroy_vport_work_array(phba, vports); | 401 | lpfc_destroy_vport_work_array(phba, vports); |
@@ -402,7 +419,6 @@ lpfc_ramp_up_queue_handler(struct lpfc_hba *phba) | |||
402 | struct Scsi_Host *shost; | 419 | struct Scsi_Host *shost; |
403 | struct scsi_device *sdev; | 420 | struct scsi_device *sdev; |
404 | int i; | 421 | int i; |
405 | struct lpfc_rport_data *rdata; | ||
406 | 422 | ||
407 | vports = lpfc_create_vport_work_array(phba); | 423 | vports = lpfc_create_vport_work_array(phba); |
408 | if (vports != NULL) | 424 | if (vports != NULL) |
@@ -412,22 +428,9 @@ lpfc_ramp_up_queue_handler(struct lpfc_hba *phba) | |||
412 | if (vports[i]->cfg_lun_queue_depth <= | 428 | if (vports[i]->cfg_lun_queue_depth <= |
413 | sdev->queue_depth) | 429 | sdev->queue_depth) |
414 | continue; | 430 | continue; |
415 | if (sdev->ordered_tags) | 431 | lpfc_change_queue_depth(sdev, |
416 | scsi_adjust_queue_depth(sdev, | 432 | sdev->queue_depth+1, |
417 | MSG_ORDERED_TAG, | 433 | SCSI_QDEPTH_RAMP_UP); |
418 | sdev->queue_depth+1); | ||
419 | else | ||
420 | scsi_adjust_queue_depth(sdev, | ||
421 | MSG_SIMPLE_TAG, | ||
422 | sdev->queue_depth+1); | ||
423 | rdata = sdev->hostdata; | ||
424 | if (rdata) | ||
425 | lpfc_send_sdev_queuedepth_change_event( | ||
426 | phba, vports[i], | ||
427 | rdata->pnode, | ||
428 | sdev->lun, | ||
429 | sdev->queue_depth - 1, | ||
430 | sdev->queue_depth); | ||
431 | } | 434 | } |
432 | } | 435 | } |
433 | lpfc_destroy_vport_work_array(phba, vports); | 436 | lpfc_destroy_vport_work_array(phba, vports); |
@@ -2208,7 +2211,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, | |||
2208 | struct scsi_cmnd *cmd = lpfc_cmd->pCmd; | 2211 | struct scsi_cmnd *cmd = lpfc_cmd->pCmd; |
2209 | int result; | 2212 | int result; |
2210 | struct scsi_device *tmp_sdev; | 2213 | struct scsi_device *tmp_sdev; |
2211 | int depth = 0; | 2214 | int depth; |
2212 | unsigned long flags; | 2215 | unsigned long flags; |
2213 | struct lpfc_fast_path_event *fast_path_evt; | 2216 | struct lpfc_fast_path_event *fast_path_evt; |
2214 | struct Scsi_Host *shost = cmd->device->host; | 2217 | struct Scsi_Host *shost = cmd->device->host; |
@@ -2375,67 +2378,29 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, | |||
2375 | return; | 2378 | return; |
2376 | } | 2379 | } |
2377 | 2380 | ||
2378 | |||
2379 | if (!result) | 2381 | if (!result) |
2380 | lpfc_rampup_queue_depth(vport, queue_depth); | 2382 | lpfc_rampup_queue_depth(vport, queue_depth); |
2381 | 2383 | ||
2382 | if (!result && pnode && NLP_CHK_NODE_ACT(pnode) && | ||
2383 | ((jiffies - pnode->last_ramp_up_time) > | ||
2384 | LPFC_Q_RAMP_UP_INTERVAL * HZ) && | ||
2385 | ((jiffies - pnode->last_q_full_time) > | ||
2386 | LPFC_Q_RAMP_UP_INTERVAL * HZ) && | ||
2387 | (vport->cfg_lun_queue_depth > queue_depth)) { | ||
2388 | shost_for_each_device(tmp_sdev, shost) { | ||
2389 | if (vport->cfg_lun_queue_depth > tmp_sdev->queue_depth){ | ||
2390 | if (tmp_sdev->id != scsi_id) | ||
2391 | continue; | ||
2392 | if (tmp_sdev->ordered_tags) | ||
2393 | scsi_adjust_queue_depth(tmp_sdev, | ||
2394 | MSG_ORDERED_TAG, | ||
2395 | tmp_sdev->queue_depth+1); | ||
2396 | else | ||
2397 | scsi_adjust_queue_depth(tmp_sdev, | ||
2398 | MSG_SIMPLE_TAG, | ||
2399 | tmp_sdev->queue_depth+1); | ||
2400 | |||
2401 | pnode->last_ramp_up_time = jiffies; | ||
2402 | } | ||
2403 | } | ||
2404 | lpfc_send_sdev_queuedepth_change_event(phba, vport, pnode, | ||
2405 | 0xFFFFFFFF, | ||
2406 | queue_depth , queue_depth + 1); | ||
2407 | } | ||
2408 | |||
2409 | /* | 2384 | /* |
2410 | * Check for queue full. If the lun is reporting queue full, then | 2385 | * Check for queue full. If the lun is reporting queue full, then |
2411 | * back off the lun queue depth to prevent target overloads. | 2386 | * back off the lun queue depth to prevent target overloads. |
2412 | */ | 2387 | */ |
2413 | if (result == SAM_STAT_TASK_SET_FULL && pnode && | 2388 | if (result == SAM_STAT_TASK_SET_FULL && pnode && |
2414 | NLP_CHK_NODE_ACT(pnode)) { | 2389 | NLP_CHK_NODE_ACT(pnode)) { |
2415 | pnode->last_q_full_time = jiffies; | ||
2416 | |||
2417 | shost_for_each_device(tmp_sdev, shost) { | 2390 | shost_for_each_device(tmp_sdev, shost) { |
2418 | if (tmp_sdev->id != scsi_id) | 2391 | if (tmp_sdev->id != scsi_id) |
2419 | continue; | 2392 | continue; |
2420 | depth = scsi_track_queue_full(tmp_sdev, | 2393 | depth = scsi_track_queue_full(tmp_sdev, |
2421 | tmp_sdev->queue_depth - 1); | 2394 | tmp_sdev->queue_depth-1); |
2422 | } | 2395 | if (depth <= 0) |
2423 | /* | 2396 | continue; |
2424 | * The queue depth cannot be lowered any more. | ||
2425 | * Modify the returned error code to store | ||
2426 | * the final depth value set by | ||
2427 | * scsi_track_queue_full. | ||
2428 | */ | ||
2429 | if (depth == -1) | ||
2430 | depth = shost->cmd_per_lun; | ||
2431 | |||
2432 | if (depth) { | ||
2433 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, | 2397 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, |
2434 | "0711 detected queue full - lun queue " | 2398 | "0711 detected queue full - lun queue " |
2435 | "depth adjusted to %d.\n", depth); | 2399 | "depth adjusted to %d.\n", depth); |
2436 | lpfc_send_sdev_queuedepth_change_event(phba, vport, | 2400 | lpfc_send_sdev_queuedepth_change_event(phba, vport, |
2437 | pnode, 0xFFFFFFFF, | 2401 | pnode, |
2438 | depth+1, depth); | 2402 | tmp_sdev->lun, |
2403 | depth+1, depth); | ||
2439 | } | 2404 | } |
2440 | } | 2405 | } |
2441 | 2406 | ||
@@ -3019,6 +2984,10 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) | |||
3019 | 2984 | ||
3020 | icmd->ulpLe = 1; | 2985 | icmd->ulpLe = 1; |
3021 | icmd->ulpClass = cmd->ulpClass; | 2986 | icmd->ulpClass = cmd->ulpClass; |
2987 | |||
2988 | /* ABTS WQE must go to the same WQ as the WQE to be aborted */ | ||
2989 | abtsiocb->fcp_wqidx = iocb->fcp_wqidx; | ||
2990 | |||
3022 | if (lpfc_is_link_up(phba)) | 2991 | if (lpfc_is_link_up(phba)) |
3023 | icmd->ulpCommand = CMD_ABORT_XRI_CN; | 2992 | icmd->ulpCommand = CMD_ABORT_XRI_CN; |
3024 | else | 2993 | else |
@@ -3596,6 +3565,7 @@ struct scsi_host_template lpfc_template = { | |||
3596 | .shost_attrs = lpfc_hba_attrs, | 3565 | .shost_attrs = lpfc_hba_attrs, |
3597 | .max_sectors = 0xFFFF, | 3566 | .max_sectors = 0xFFFF, |
3598 | .vendor_id = LPFC_NL_VENDOR_ID, | 3567 | .vendor_id = LPFC_NL_VENDOR_ID, |
3568 | .change_queue_depth = lpfc_change_queue_depth, | ||
3599 | }; | 3569 | }; |
3600 | 3570 | ||
3601 | struct scsi_host_template lpfc_vport_template = { | 3571 | struct scsi_host_template lpfc_vport_template = { |
@@ -3617,4 +3587,5 @@ struct scsi_host_template lpfc_vport_template = { | |||
3617 | .use_clustering = ENABLE_CLUSTERING, | 3587 | .use_clustering = ENABLE_CLUSTERING, |
3618 | .shost_attrs = lpfc_vport_attrs, | 3588 | .shost_attrs = lpfc_vport_attrs, |
3619 | .max_sectors = 0xFFFF, | 3589 | .max_sectors = 0xFFFF, |
3590 | .change_queue_depth = lpfc_change_queue_depth, | ||
3620 | }; | 3591 | }; |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index ce0a1a1c4792..1d2f65c4eb0b 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -5748,7 +5748,7 @@ static int | |||
5748 | lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, | 5748 | lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, |
5749 | union lpfc_wqe *wqe) | 5749 | union lpfc_wqe *wqe) |
5750 | { | 5750 | { |
5751 | uint32_t payload_len = 0; | 5751 | uint32_t xmit_len = 0, total_len = 0; |
5752 | uint8_t ct = 0; | 5752 | uint8_t ct = 0; |
5753 | uint32_t fip; | 5753 | uint32_t fip; |
5754 | uint32_t abort_tag; | 5754 | uint32_t abort_tag; |
@@ -5757,6 +5757,8 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, | |||
5757 | uint16_t xritag; | 5757 | uint16_t xritag; |
5758 | struct ulp_bde64 *bpl = NULL; | 5758 | struct ulp_bde64 *bpl = NULL; |
5759 | uint32_t els_id = ELS_ID_DEFAULT; | 5759 | uint32_t els_id = ELS_ID_DEFAULT; |
5760 | int numBdes, i; | ||
5761 | struct ulp_bde64 bde; | ||
5760 | 5762 | ||
5761 | fip = phba->hba_flag & HBA_FIP_SUPPORT; | 5763 | fip = phba->hba_flag & HBA_FIP_SUPPORT; |
5762 | /* The fcp commands will set command type */ | 5764 | /* The fcp commands will set command type */ |
@@ -5774,6 +5776,8 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, | |||
5774 | wqe->words[7] = 0; /* The ct field has moved so reset */ | 5776 | wqe->words[7] = 0; /* The ct field has moved so reset */ |
5775 | /* words0-2 bpl convert bde */ | 5777 | /* words0-2 bpl convert bde */ |
5776 | if (iocbq->iocb.un.genreq64.bdl.bdeFlags == BUFF_TYPE_BLP_64) { | 5778 | if (iocbq->iocb.un.genreq64.bdl.bdeFlags == BUFF_TYPE_BLP_64) { |
5779 | numBdes = iocbq->iocb.un.genreq64.bdl.bdeSize / | ||
5780 | sizeof(struct ulp_bde64); | ||
5777 | bpl = (struct ulp_bde64 *) | 5781 | bpl = (struct ulp_bde64 *) |
5778 | ((struct lpfc_dmabuf *)iocbq->context3)->virt; | 5782 | ((struct lpfc_dmabuf *)iocbq->context3)->virt; |
5779 | if (!bpl) | 5783 | if (!bpl) |
@@ -5786,9 +5790,14 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, | |||
5786 | * can assign it to the sgl. | 5790 | * can assign it to the sgl. |
5787 | */ | 5791 | */ |
5788 | wqe->generic.bde.tus.w = le32_to_cpu(bpl->tus.w); | 5792 | wqe->generic.bde.tus.w = le32_to_cpu(bpl->tus.w); |
5789 | payload_len = wqe->generic.bde.tus.f.bdeSize; | 5793 | xmit_len = wqe->generic.bde.tus.f.bdeSize; |
5794 | total_len = 0; | ||
5795 | for (i = 0; i < numBdes; i++) { | ||
5796 | bde.tus.w = le32_to_cpu(bpl[i].tus.w); | ||
5797 | total_len += bde.tus.f.bdeSize; | ||
5798 | } | ||
5790 | } else | 5799 | } else |
5791 | payload_len = iocbq->iocb.un.fcpi64.bdl.bdeSize; | 5800 | xmit_len = iocbq->iocb.un.fcpi64.bdl.bdeSize; |
5792 | 5801 | ||
5793 | iocbq->iocb.ulpIoTag = iocbq->iotag; | 5802 | iocbq->iocb.ulpIoTag = iocbq->iotag; |
5794 | cmnd = iocbq->iocb.ulpCommand; | 5803 | cmnd = iocbq->iocb.ulpCommand; |
@@ -5802,7 +5811,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, | |||
5802 | iocbq->iocb.ulpCommand); | 5811 | iocbq->iocb.ulpCommand); |
5803 | return IOCB_ERROR; | 5812 | return IOCB_ERROR; |
5804 | } | 5813 | } |
5805 | wqe->els_req.payload_len = payload_len; | 5814 | wqe->els_req.payload_len = xmit_len; |
5806 | /* Els_reguest64 has a TMO */ | 5815 | /* Els_reguest64 has a TMO */ |
5807 | bf_set(wqe_tmo, &wqe->els_req.wqe_com, | 5816 | bf_set(wqe_tmo, &wqe->els_req.wqe_com, |
5808 | iocbq->iocb.ulpTimeout); | 5817 | iocbq->iocb.ulpTimeout); |
@@ -5831,6 +5840,15 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, | |||
5831 | bf_set(lpfc_wqe_gen_els_id, &wqe->generic, els_id); | 5840 | bf_set(lpfc_wqe_gen_els_id, &wqe->generic, els_id); |
5832 | 5841 | ||
5833 | break; | 5842 | break; |
5843 | case CMD_XMIT_SEQUENCE64_CX: | ||
5844 | bf_set(lpfc_wqe_gen_context, &wqe->generic, | ||
5845 | iocbq->iocb.un.ulpWord[3]); | ||
5846 | wqe->generic.word3 = 0; | ||
5847 | bf_set(wqe_rcvoxid, &wqe->generic, iocbq->iocb.ulpContext); | ||
5848 | bf_set(wqe_xc, &wqe->generic, 1); | ||
5849 | /* The entire sequence is transmitted for this IOCB */ | ||
5850 | xmit_len = total_len; | ||
5851 | cmnd = CMD_XMIT_SEQUENCE64_CR; | ||
5834 | case CMD_XMIT_SEQUENCE64_CR: | 5852 | case CMD_XMIT_SEQUENCE64_CR: |
5835 | /* word3 iocb=io_tag32 wqe=payload_offset */ | 5853 | /* word3 iocb=io_tag32 wqe=payload_offset */ |
5836 | /* payload offset used for multilpe outstanding | 5854 | /* payload offset used for multilpe outstanding |
@@ -5840,7 +5858,8 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, | |||
5840 | /* word4 relative_offset memcpy */ | 5858 | /* word4 relative_offset memcpy */ |
5841 | /* word5 r_ctl/df_ctl memcpy */ | 5859 | /* word5 r_ctl/df_ctl memcpy */ |
5842 | bf_set(lpfc_wqe_gen_pu, &wqe->generic, 0); | 5860 | bf_set(lpfc_wqe_gen_pu, &wqe->generic, 0); |
5843 | wqe->xmit_sequence.xmit_len = payload_len; | 5861 | wqe->xmit_sequence.xmit_len = xmit_len; |
5862 | command_type = OTHER_COMMAND; | ||
5844 | break; | 5863 | break; |
5845 | case CMD_XMIT_BCAST64_CN: | 5864 | case CMD_XMIT_BCAST64_CN: |
5846 | /* word3 iocb=iotag32 wqe=payload_len */ | 5865 | /* word3 iocb=iotag32 wqe=payload_len */ |
@@ -5869,7 +5888,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, | |||
5869 | case CMD_FCP_IREAD64_CR: | 5888 | case CMD_FCP_IREAD64_CR: |
5870 | /* FCP_CMD is always the 1st sgl entry */ | 5889 | /* FCP_CMD is always the 1st sgl entry */ |
5871 | wqe->fcp_iread.payload_len = | 5890 | wqe->fcp_iread.payload_len = |
5872 | payload_len + sizeof(struct fcp_rsp); | 5891 | xmit_len + sizeof(struct fcp_rsp); |
5873 | 5892 | ||
5874 | /* word 4 (xfer length) should have been set on the memcpy */ | 5893 | /* word 4 (xfer length) should have been set on the memcpy */ |
5875 | 5894 | ||
@@ -5906,7 +5925,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, | |||
5906 | * sgl[1] = rsp. | 5925 | * sgl[1] = rsp. |
5907 | * | 5926 | * |
5908 | */ | 5927 | */ |
5909 | wqe->gen_req.command_len = payload_len; | 5928 | wqe->gen_req.command_len = xmit_len; |
5910 | /* Word4 parameter copied in the memcpy */ | 5929 | /* Word4 parameter copied in the memcpy */ |
5911 | /* Word5 [rctl, type, df_ctl, la] copied in memcpy */ | 5930 | /* Word5 [rctl, type, df_ctl, la] copied in memcpy */ |
5912 | /* word6 context tag copied in memcpy */ | 5931 | /* word6 context tag copied in memcpy */ |
@@ -5979,10 +5998,25 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, | |||
5979 | * iocbq from scratch. | 5998 | * iocbq from scratch. |
5980 | */ | 5999 | */ |
5981 | memset(wqe, 0, sizeof(union lpfc_wqe)); | 6000 | memset(wqe, 0, sizeof(union lpfc_wqe)); |
6001 | /* OX_ID is invariable to who sent ABTS to CT exchange */ | ||
5982 | bf_set(xmit_bls_rsp64_oxid, &wqe->xmit_bls_rsp, | 6002 | bf_set(xmit_bls_rsp64_oxid, &wqe->xmit_bls_rsp, |
5983 | iocbq->iocb.un.ulpWord[3]); | 6003 | bf_get(lpfc_abts_oxid, &iocbq->iocb.un.bls_acc)); |
5984 | bf_set(xmit_bls_rsp64_rxid, &wqe->xmit_bls_rsp, | 6004 | if (bf_get(lpfc_abts_orig, &iocbq->iocb.un.bls_acc) == |
5985 | iocbq->sli4_xritag); | 6005 | LPFC_ABTS_UNSOL_INT) { |
6006 | /* ABTS sent by initiator to CT exchange, the | ||
6007 | * RX_ID field will be filled with the newly | ||
6008 | * allocated responder XRI. | ||
6009 | */ | ||
6010 | bf_set(xmit_bls_rsp64_rxid, &wqe->xmit_bls_rsp, | ||
6011 | iocbq->sli4_xritag); | ||
6012 | } else { | ||
6013 | /* ABTS sent by responder to CT exchange, the | ||
6014 | * RX_ID field will be filled with the responder | ||
6015 | * RX_ID from ABTS. | ||
6016 | */ | ||
6017 | bf_set(xmit_bls_rsp64_rxid, &wqe->xmit_bls_rsp, | ||
6018 | bf_get(lpfc_abts_rxid, &iocbq->iocb.un.bls_acc)); | ||
6019 | } | ||
5986 | bf_set(xmit_bls_rsp64_seqcnthi, &wqe->xmit_bls_rsp, 0xffff); | 6020 | bf_set(xmit_bls_rsp64_seqcnthi, &wqe->xmit_bls_rsp, 0xffff); |
5987 | bf_set(wqe_xmit_bls_pt, &wqe->xmit_bls_rsp.wqe_dest, 0x1); | 6021 | bf_set(wqe_xmit_bls_pt, &wqe->xmit_bls_rsp.wqe_dest, 0x1); |
5988 | bf_set(wqe_ctxt_tag, &wqe->xmit_bls_rsp.wqe_com, | 6022 | bf_set(wqe_ctxt_tag, &wqe->xmit_bls_rsp.wqe_com, |
@@ -6044,7 +6078,6 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, | |||
6044 | uint16_t xritag; | 6078 | uint16_t xritag; |
6045 | union lpfc_wqe wqe; | 6079 | union lpfc_wqe wqe; |
6046 | struct lpfc_sli_ring *pring = &phba->sli.ring[ring_number]; | 6080 | struct lpfc_sli_ring *pring = &phba->sli.ring[ring_number]; |
6047 | uint32_t fcp_wqidx; | ||
6048 | 6081 | ||
6049 | if (piocb->sli4_xritag == NO_XRI) { | 6082 | if (piocb->sli4_xritag == NO_XRI) { |
6050 | if (piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN || | 6083 | if (piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN || |
@@ -6079,8 +6112,17 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, | |||
6079 | return IOCB_ERROR; | 6112 | return IOCB_ERROR; |
6080 | 6113 | ||
6081 | if (piocb->iocb_flag & LPFC_IO_FCP) { | 6114 | if (piocb->iocb_flag & LPFC_IO_FCP) { |
6082 | fcp_wqidx = lpfc_sli4_scmd_to_wqidx_distr(phba); | 6115 | /* |
6083 | if (lpfc_sli4_wq_put(phba->sli4_hba.fcp_wq[fcp_wqidx], &wqe)) | 6116 | * For FCP command IOCB, get a new WQ index to distribute |
6117 | * WQE across the WQsr. On the other hand, for abort IOCB, | ||
6118 | * it carries the same WQ index to the original command | ||
6119 | * IOCB. | ||
6120 | */ | ||
6121 | if ((piocb->iocb.ulpCommand != CMD_ABORT_XRI_CN) && | ||
6122 | (piocb->iocb.ulpCommand != CMD_CLOSE_XRI_CN)) | ||
6123 | piocb->fcp_wqidx = lpfc_sli4_scmd_to_wqidx_distr(phba); | ||
6124 | if (lpfc_sli4_wq_put(phba->sli4_hba.fcp_wq[piocb->fcp_wqidx], | ||
6125 | &wqe)) | ||
6084 | return IOCB_ERROR; | 6126 | return IOCB_ERROR; |
6085 | } else { | 6127 | } else { |
6086 | if (lpfc_sli4_wq_put(phba->sli4_hba.els_wq, &wqe)) | 6128 | if (lpfc_sli4_wq_put(phba->sli4_hba.els_wq, &wqe)) |
@@ -7070,6 +7112,9 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
7070 | iabt->ulpLe = 1; | 7112 | iabt->ulpLe = 1; |
7071 | iabt->ulpClass = icmd->ulpClass; | 7113 | iabt->ulpClass = icmd->ulpClass; |
7072 | 7114 | ||
7115 | /* ABTS WQE must go to the same WQ as the WQE to be aborted */ | ||
7116 | abtsiocbp->fcp_wqidx = cmdiocb->fcp_wqidx; | ||
7117 | |||
7073 | if (phba->link_state >= LPFC_LINK_UP) | 7118 | if (phba->link_state >= LPFC_LINK_UP) |
7074 | iabt->ulpCommand = CMD_ABORT_XRI_CN; | 7119 | iabt->ulpCommand = CMD_ABORT_XRI_CN; |
7075 | else | 7120 | else |
@@ -7273,6 +7318,9 @@ lpfc_sli_abort_iocb(struct lpfc_vport *vport, struct lpfc_sli_ring *pring, | |||
7273 | abtsiocb->iocb.ulpClass = cmd->ulpClass; | 7318 | abtsiocb->iocb.ulpClass = cmd->ulpClass; |
7274 | abtsiocb->vport = phba->pport; | 7319 | abtsiocb->vport = phba->pport; |
7275 | 7320 | ||
7321 | /* ABTS WQE must go to the same WQ as the WQE to be aborted */ | ||
7322 | abtsiocb->fcp_wqidx = iocbq->fcp_wqidx; | ||
7323 | |||
7276 | if (lpfc_is_link_up(phba)) | 7324 | if (lpfc_is_link_up(phba)) |
7277 | abtsiocb->iocb.ulpCommand = CMD_ABORT_XRI_CN; | 7325 | abtsiocb->iocb.ulpCommand = CMD_ABORT_XRI_CN; |
7278 | else | 7326 | else |
@@ -8671,7 +8719,6 @@ lpfc_sli4_sp_handle_rcqe(struct lpfc_hba *phba, struct lpfc_rcqe *rcqe) | |||
8671 | uint32_t status; | 8719 | uint32_t status; |
8672 | unsigned long iflags; | 8720 | unsigned long iflags; |
8673 | 8721 | ||
8674 | lpfc_sli4_rq_release(hrq, drq); | ||
8675 | if (bf_get(lpfc_rcqe_rq_id, rcqe) != hrq->queue_id) | 8722 | if (bf_get(lpfc_rcqe_rq_id, rcqe) != hrq->queue_id) |
8676 | goto out; | 8723 | goto out; |
8677 | 8724 | ||
@@ -8681,6 +8728,7 @@ lpfc_sli4_sp_handle_rcqe(struct lpfc_hba *phba, struct lpfc_rcqe *rcqe) | |||
8681 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | 8728 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, |
8682 | "2537 Receive Frame Truncated!!\n"); | 8729 | "2537 Receive Frame Truncated!!\n"); |
8683 | case FC_STATUS_RQ_SUCCESS: | 8730 | case FC_STATUS_RQ_SUCCESS: |
8731 | lpfc_sli4_rq_release(hrq, drq); | ||
8684 | spin_lock_irqsave(&phba->hbalock, iflags); | 8732 | spin_lock_irqsave(&phba->hbalock, iflags); |
8685 | dma_buf = lpfc_sli_hbqbuf_get(&phba->hbqs[0].hbq_buffer_list); | 8733 | dma_buf = lpfc_sli_hbqbuf_get(&phba->hbqs[0].hbq_buffer_list); |
8686 | if (!dma_buf) { | 8734 | if (!dma_buf) { |
@@ -10997,8 +11045,8 @@ lpfc_sli4_seq_abort_acc(struct lpfc_hba *phba, | |||
10997 | { | 11045 | { |
10998 | struct lpfc_iocbq *ctiocb = NULL; | 11046 | struct lpfc_iocbq *ctiocb = NULL; |
10999 | struct lpfc_nodelist *ndlp; | 11047 | struct lpfc_nodelist *ndlp; |
11000 | uint16_t oxid; | 11048 | uint16_t oxid, rxid; |
11001 | uint32_t sid; | 11049 | uint32_t sid, fctl; |
11002 | IOCB_t *icmd; | 11050 | IOCB_t *icmd; |
11003 | 11051 | ||
11004 | if (!lpfc_is_link_up(phba)) | 11052 | if (!lpfc_is_link_up(phba)) |
@@ -11006,6 +11054,7 @@ lpfc_sli4_seq_abort_acc(struct lpfc_hba *phba, | |||
11006 | 11054 | ||
11007 | sid = sli4_sid_from_fc_hdr(fc_hdr); | 11055 | sid = sli4_sid_from_fc_hdr(fc_hdr); |
11008 | oxid = be16_to_cpu(fc_hdr->fh_ox_id); | 11056 | oxid = be16_to_cpu(fc_hdr->fh_ox_id); |
11057 | rxid = be16_to_cpu(fc_hdr->fh_rx_id); | ||
11009 | 11058 | ||
11010 | ndlp = lpfc_findnode_did(phba->pport, sid); | 11059 | ndlp = lpfc_findnode_did(phba->pport, sid); |
11011 | if (!ndlp) { | 11060 | if (!ndlp) { |
@@ -11020,9 +11069,12 @@ lpfc_sli4_seq_abort_acc(struct lpfc_hba *phba, | |||
11020 | if (!ctiocb) | 11069 | if (!ctiocb) |
11021 | return; | 11070 | return; |
11022 | 11071 | ||
11072 | /* Extract the F_CTL field from FC_HDR */ | ||
11073 | fctl = sli4_fctl_from_fc_hdr(fc_hdr); | ||
11074 | |||
11023 | icmd = &ctiocb->iocb; | 11075 | icmd = &ctiocb->iocb; |
11024 | icmd->un.xseq64.bdl.ulpIoTag32 = 0; | ||
11025 | icmd->un.xseq64.bdl.bdeSize = 0; | 11076 | icmd->un.xseq64.bdl.bdeSize = 0; |
11077 | icmd->un.xseq64.bdl.ulpIoTag32 = 0; | ||
11026 | icmd->un.xseq64.w5.hcsw.Dfctl = 0; | 11078 | icmd->un.xseq64.w5.hcsw.Dfctl = 0; |
11027 | icmd->un.xseq64.w5.hcsw.Rctl = FC_RCTL_BA_ACC; | 11079 | icmd->un.xseq64.w5.hcsw.Rctl = FC_RCTL_BA_ACC; |
11028 | icmd->un.xseq64.w5.hcsw.Type = FC_TYPE_BLS; | 11080 | icmd->un.xseq64.w5.hcsw.Type = FC_TYPE_BLS; |
@@ -11033,13 +11085,30 @@ lpfc_sli4_seq_abort_acc(struct lpfc_hba *phba, | |||
11033 | icmd->ulpLe = 1; | 11085 | icmd->ulpLe = 1; |
11034 | icmd->ulpClass = CLASS3; | 11086 | icmd->ulpClass = CLASS3; |
11035 | icmd->ulpContext = ndlp->nlp_rpi; | 11087 | icmd->ulpContext = ndlp->nlp_rpi; |
11036 | icmd->un.ulpWord[3] = oxid; | ||
11037 | 11088 | ||
11038 | ctiocb->sli4_xritag = NO_XRI; | ||
11039 | ctiocb->iocb_cmpl = NULL; | 11089 | ctiocb->iocb_cmpl = NULL; |
11040 | ctiocb->vport = phba->pport; | 11090 | ctiocb->vport = phba->pport; |
11041 | ctiocb->iocb_cmpl = lpfc_sli4_seq_abort_acc_cmpl; | 11091 | ctiocb->iocb_cmpl = lpfc_sli4_seq_abort_acc_cmpl; |
11042 | 11092 | ||
11093 | if (fctl & FC_FC_EX_CTX) { | ||
11094 | /* ABTS sent by responder to CT exchange, construction | ||
11095 | * of BA_ACC will use OX_ID from ABTS for the XRI_TAG | ||
11096 | * field and RX_ID from ABTS for RX_ID field. | ||
11097 | */ | ||
11098 | bf_set(lpfc_abts_orig, &icmd->un.bls_acc, LPFC_ABTS_UNSOL_RSP); | ||
11099 | bf_set(lpfc_abts_rxid, &icmd->un.bls_acc, rxid); | ||
11100 | ctiocb->sli4_xritag = oxid; | ||
11101 | } else { | ||
11102 | /* ABTS sent by initiator to CT exchange, construction | ||
11103 | * of BA_ACC will need to allocate a new XRI as for the | ||
11104 | * XRI_TAG and RX_ID fields. | ||
11105 | */ | ||
11106 | bf_set(lpfc_abts_orig, &icmd->un.bls_acc, LPFC_ABTS_UNSOL_INT); | ||
11107 | bf_set(lpfc_abts_rxid, &icmd->un.bls_acc, NO_XRI); | ||
11108 | ctiocb->sli4_xritag = NO_XRI; | ||
11109 | } | ||
11110 | bf_set(lpfc_abts_oxid, &icmd->un.bls_acc, oxid); | ||
11111 | |||
11043 | /* Xmit CT abts accept on exchange <xid> */ | 11112 | /* Xmit CT abts accept on exchange <xid> */ |
11044 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | 11113 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, |
11045 | "1200 Xmit CT ABTS ACC on exchange x%x Data: x%x\n", | 11114 | "1200 Xmit CT ABTS ACC on exchange x%x Data: x%x\n", |
@@ -11066,19 +11135,31 @@ lpfc_sli4_handle_unsol_abort(struct lpfc_vport *vport, | |||
11066 | { | 11135 | { |
11067 | struct lpfc_hba *phba = vport->phba; | 11136 | struct lpfc_hba *phba = vport->phba; |
11068 | struct fc_frame_header fc_hdr; | 11137 | struct fc_frame_header fc_hdr; |
11138 | uint32_t fctl; | ||
11069 | bool abts_par; | 11139 | bool abts_par; |
11070 | 11140 | ||
11071 | /* Try to abort partially assembled seq */ | ||
11072 | abts_par = lpfc_sli4_abort_partial_seq(vport, dmabuf); | ||
11073 | |||
11074 | /* Make a copy of fc_hdr before the dmabuf being released */ | 11141 | /* Make a copy of fc_hdr before the dmabuf being released */ |
11075 | memcpy(&fc_hdr, dmabuf->hbuf.virt, sizeof(struct fc_frame_header)); | 11142 | memcpy(&fc_hdr, dmabuf->hbuf.virt, sizeof(struct fc_frame_header)); |
11143 | fctl = sli4_fctl_from_fc_hdr(&fc_hdr); | ||
11076 | 11144 | ||
11077 | /* Send abort to ULP if partially seq abort failed */ | 11145 | if (fctl & FC_FC_EX_CTX) { |
11078 | if (abts_par == false) | 11146 | /* |
11079 | lpfc_sli4_send_seq_to_ulp(vport, dmabuf); | 11147 | * ABTS sent by responder to exchange, just free the buffer |
11080 | else | 11148 | */ |
11081 | lpfc_in_buf_free(phba, &dmabuf->dbuf); | 11149 | lpfc_in_buf_free(phba, &dmabuf->dbuf); |
11150 | } else { | ||
11151 | /* | ||
11152 | * ABTS sent by initiator to exchange, need to do cleanup | ||
11153 | */ | ||
11154 | /* Try to abort partially assembled seq */ | ||
11155 | abts_par = lpfc_sli4_abort_partial_seq(vport, dmabuf); | ||
11156 | |||
11157 | /* Send abort to ULP if partially seq abort failed */ | ||
11158 | if (abts_par == false) | ||
11159 | lpfc_sli4_send_seq_to_ulp(vport, dmabuf); | ||
11160 | else | ||
11161 | lpfc_in_buf_free(phba, &dmabuf->dbuf); | ||
11162 | } | ||
11082 | /* Send basic accept (BA_ACC) to the abort requester */ | 11163 | /* Send basic accept (BA_ACC) to the abort requester */ |
11083 | lpfc_sli4_seq_abort_acc(phba, &fc_hdr); | 11164 | lpfc_sli4_seq_abort_acc(phba, &fc_hdr); |
11084 | } | 11165 | } |
diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h index 174dcda32195..ba38de3c28f1 100644 --- a/drivers/scsi/lpfc/lpfc_sli.h +++ b/drivers/scsi/lpfc/lpfc_sli.h | |||
@@ -66,6 +66,7 @@ struct lpfc_iocbq { | |||
66 | uint8_t abort_count; | 66 | uint8_t abort_count; |
67 | uint8_t rsvd2; | 67 | uint8_t rsvd2; |
68 | uint32_t drvrTimeout; /* driver timeout in seconds */ | 68 | uint32_t drvrTimeout; /* driver timeout in seconds */ |
69 | uint32_t fcp_wqidx; /* index to FCP work queue */ | ||
69 | struct lpfc_vport *vport;/* virtual port pointer */ | 70 | struct lpfc_vport *vport;/* virtual port pointer */ |
70 | void *context1; /* caller context information */ | 71 | void *context1; /* caller context information */ |
71 | void *context2; /* caller context information */ | 72 | void *context2; /* caller context information */ |
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index 4a9cf674555e..6a4558ba93b6 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h | |||
@@ -63,6 +63,11 @@ | |||
63 | (fc_hdr)->fh_s_id[1] << 8 | \ | 63 | (fc_hdr)->fh_s_id[1] << 8 | \ |
64 | (fc_hdr)->fh_s_id[2]) | 64 | (fc_hdr)->fh_s_id[2]) |
65 | 65 | ||
66 | #define sli4_fctl_from_fc_hdr(fc_hdr) \ | ||
67 | ((fc_hdr)->fh_f_ctl[0] << 16 | \ | ||
68 | (fc_hdr)->fh_f_ctl[1] << 8 | \ | ||
69 | (fc_hdr)->fh_f_ctl[2]) | ||
70 | |||
66 | enum lpfc_sli4_queue_type { | 71 | enum lpfc_sli4_queue_type { |
67 | LPFC_EQ, | 72 | LPFC_EQ, |
68 | LPFC_GCQ, | 73 | LPFC_GCQ, |
diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index 096d178c4c86..7d6dd83d3592 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c | |||
@@ -700,6 +700,8 @@ lpfc_vport_delete(struct fc_vport *fc_vport) | |||
700 | } | 700 | } |
701 | spin_unlock_irq(&phba->ndlp_lock); | 701 | spin_unlock_irq(&phba->ndlp_lock); |
702 | } | 702 | } |
703 | if (vport->vpi_state != LPFC_VPI_REGISTERED) | ||
704 | goto skip_logo; | ||
703 | vport->unreg_vpi_cmpl = VPORT_INVAL; | 705 | vport->unreg_vpi_cmpl = VPORT_INVAL; |
704 | timeout = msecs_to_jiffies(phba->fc_ratov * 2000); | 706 | timeout = msecs_to_jiffies(phba->fc_ratov * 2000); |
705 | if (!lpfc_issue_els_npiv_logo(vport, ndlp)) | 707 | if (!lpfc_issue_els_npiv_logo(vport, ndlp)) |