diff options
author | James Smart <james.smart@emulex.com> | 2010-11-20 23:11:55 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-12-21 13:24:01 -0500 |
commit | 19ca760979e4be41a3eb215fb8d0e96637161947 (patch) | |
tree | de6c32815eb813ba770a26178c1612015acf719b | |
parent | 76a95d75ede64e4f1684ddb8c626fdfdb641bda2 (diff) |
[SCSI] lpfc 8.3.19: Added support for ELS RRQ command
Added support for ELS RRQ command
- Add new routine lpfc_set_rrq_active() to track XRI qualifier state.
- Add new module parameter lpfc_enable_rrq to control RRQ operation.
- Add logic to ELS RRQ completion handler and xri qualifier timeout
to clear XRI qualifier state.
- Use OX_ID from XRI_ABORTED_CQE for RRQ payload.
- Tie abort and XRI_ABORTED_CQE andler to RRQ generation.
Signed-off-by: Alex Iannicelli <alex.iannicelli@emulex.com>
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 7 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_attr.c | 9 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 12 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_disc.h | 17 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 232 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 4 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hw.h | 18 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 34 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_mem.c | 10 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 82 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 396 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.h | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli4.h | 1 |
13 files changed, 803 insertions, 20 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index e86a0d2add3c..746dd3d7a092 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
@@ -486,7 +486,7 @@ struct lpfc_hba { | |||
486 | int (*lpfc_new_scsi_buf) | 486 | int (*lpfc_new_scsi_buf) |
487 | (struct lpfc_vport *, int); | 487 | (struct lpfc_vport *, int); |
488 | struct lpfc_scsi_buf * (*lpfc_get_scsi_buf) | 488 | struct lpfc_scsi_buf * (*lpfc_get_scsi_buf) |
489 | (struct lpfc_hba *); | 489 | (struct lpfc_hba *, struct lpfc_nodelist *); |
490 | int (*lpfc_scsi_prep_dma_buf) | 490 | int (*lpfc_scsi_prep_dma_buf) |
491 | (struct lpfc_hba *, struct lpfc_scsi_buf *); | 491 | (struct lpfc_hba *, struct lpfc_scsi_buf *); |
492 | void (*lpfc_scsi_unprep_dma_buf) | 492 | void (*lpfc_scsi_unprep_dma_buf) |
@@ -574,6 +574,7 @@ struct lpfc_hba { | |||
574 | #define HBA_FIP_SUPPORT 0x800 /* FIP support in HBA */ | 574 | #define HBA_FIP_SUPPORT 0x800 /* FIP support in HBA */ |
575 | #define HBA_AER_ENABLED 0x1000 /* AER enabled with HBA */ | 575 | #define HBA_AER_ENABLED 0x1000 /* AER enabled with HBA */ |
576 | #define HBA_DEVLOSS_TMO 0x2000 /* HBA in devloss timeout */ | 576 | #define HBA_DEVLOSS_TMO 0x2000 /* HBA in devloss timeout */ |
577 | #define HBA_RRQ_ACTIVE 0x4000 /* process the rrq active list */ | ||
577 | uint32_t fcp_ring_in_use; /* When polling test if intr-hndlr active*/ | 578 | uint32_t fcp_ring_in_use; /* When polling test if intr-hndlr active*/ |
578 | struct lpfc_dmabuf slim2p; | 579 | struct lpfc_dmabuf slim2p; |
579 | 580 | ||
@@ -623,6 +624,7 @@ struct lpfc_hba { | |||
623 | /* HBA Config Parameters */ | 624 | /* HBA Config Parameters */ |
624 | uint32_t cfg_ack0; | 625 | uint32_t cfg_ack0; |
625 | uint32_t cfg_enable_npiv; | 626 | uint32_t cfg_enable_npiv; |
627 | uint32_t cfg_enable_rrq; | ||
626 | uint32_t cfg_topology; | 628 | uint32_t cfg_topology; |
627 | uint32_t cfg_link_speed; | 629 | uint32_t cfg_link_speed; |
628 | uint32_t cfg_cr_delay; | 630 | uint32_t cfg_cr_delay; |
@@ -733,6 +735,7 @@ struct lpfc_hba { | |||
733 | uint32_t total_scsi_bufs; | 735 | uint32_t total_scsi_bufs; |
734 | struct list_head lpfc_iocb_list; | 736 | struct list_head lpfc_iocb_list; |
735 | uint32_t total_iocbq_bufs; | 737 | uint32_t total_iocbq_bufs; |
738 | struct list_head active_rrq_list; | ||
736 | spinlock_t hbalock; | 739 | spinlock_t hbalock; |
737 | 740 | ||
738 | /* pci_mem_pools */ | 741 | /* pci_mem_pools */ |
@@ -745,6 +748,7 @@ struct lpfc_hba { | |||
745 | 748 | ||
746 | mempool_t *mbox_mem_pool; | 749 | mempool_t *mbox_mem_pool; |
747 | mempool_t *nlp_mem_pool; | 750 | mempool_t *nlp_mem_pool; |
751 | mempool_t *rrq_pool; | ||
748 | 752 | ||
749 | struct fc_host_statistics link_stats; | 753 | struct fc_host_statistics link_stats; |
750 | enum intr_type_t intr_type; | 754 | enum intr_type_t intr_type; |
@@ -801,6 +805,7 @@ struct lpfc_hba { | |||
801 | unsigned long skipped_hb; | 805 | unsigned long skipped_hb; |
802 | struct timer_list hb_tmofunc; | 806 | struct timer_list hb_tmofunc; |
803 | uint8_t hb_outstanding; | 807 | uint8_t hb_outstanding; |
808 | struct timer_list rrq_tmr; | ||
804 | enum hba_temp_state over_temp_state; | 809 | enum hba_temp_state over_temp_state; |
805 | /* ndlp reference management */ | 810 | /* ndlp reference management */ |
806 | spinlock_t ndlp_lock; | 811 | spinlock_t ndlp_lock; |
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 45bd72a9f60e..6be942ae8a07 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c | |||
@@ -1977,6 +1977,13 @@ lpfc_param_show(enable_npiv); | |||
1977 | lpfc_param_init(enable_npiv, 1, 0, 1); | 1977 | lpfc_param_init(enable_npiv, 1, 0, 1); |
1978 | static DEVICE_ATTR(lpfc_enable_npiv, S_IRUGO, lpfc_enable_npiv_show, NULL); | 1978 | static DEVICE_ATTR(lpfc_enable_npiv, S_IRUGO, lpfc_enable_npiv_show, NULL); |
1979 | 1979 | ||
1980 | int lpfc_enable_rrq; | ||
1981 | module_param(lpfc_enable_rrq, int, 0); | ||
1982 | MODULE_PARM_DESC(lpfc_enable_rrq, "Enable RRQ functionality"); | ||
1983 | lpfc_param_show(enable_rrq); | ||
1984 | lpfc_param_init(enable_rrq, 0, 0, 1); | ||
1985 | static DEVICE_ATTR(lpfc_enable_rrq, S_IRUGO, lpfc_enable_rrq_show, NULL); | ||
1986 | |||
1980 | /* | 1987 | /* |
1981 | # lpfc_suppress_link_up: Bring link up at initialization | 1988 | # lpfc_suppress_link_up: Bring link up at initialization |
1982 | # 0x0 = bring link up (issue MBX_INIT_LINK) | 1989 | # 0x0 = bring link up (issue MBX_INIT_LINK) |
@@ -3394,6 +3401,7 @@ struct device_attribute *lpfc_hba_attrs[] = { | |||
3394 | &dev_attr_lpfc_fdmi_on, | 3401 | &dev_attr_lpfc_fdmi_on, |
3395 | &dev_attr_lpfc_max_luns, | 3402 | &dev_attr_lpfc_max_luns, |
3396 | &dev_attr_lpfc_enable_npiv, | 3403 | &dev_attr_lpfc_enable_npiv, |
3404 | &dev_attr_lpfc_enable_rrq, | ||
3397 | &dev_attr_nport_evt_cnt, | 3405 | &dev_attr_nport_evt_cnt, |
3398 | &dev_attr_board_mode, | 3406 | &dev_attr_board_mode, |
3399 | &dev_attr_max_vpi, | 3407 | &dev_attr_max_vpi, |
@@ -4610,6 +4618,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) | |||
4610 | lpfc_link_speed_init(phba, lpfc_link_speed); | 4618 | lpfc_link_speed_init(phba, lpfc_link_speed); |
4611 | lpfc_poll_tmo_init(phba, lpfc_poll_tmo); | 4619 | lpfc_poll_tmo_init(phba, lpfc_poll_tmo); |
4612 | lpfc_enable_npiv_init(phba, lpfc_enable_npiv); | 4620 | lpfc_enable_npiv_init(phba, lpfc_enable_npiv); |
4621 | lpfc_enable_rrq_init(phba, lpfc_enable_rrq); | ||
4613 | lpfc_use_msi_init(phba, lpfc_use_msi); | 4622 | lpfc_use_msi_init(phba, lpfc_use_msi); |
4614 | lpfc_fcp_imax_init(phba, lpfc_fcp_imax); | 4623 | lpfc_fcp_imax_init(phba, lpfc_fcp_imax); |
4615 | lpfc_fcp_wq_count_init(phba, lpfc_fcp_wq_count); | 4624 | lpfc_fcp_wq_count_init(phba, lpfc_fcp_wq_count); |
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 1ea3075e3c5d..9b95c50ba704 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
@@ -416,5 +416,13 @@ struct lpfc_iocbq *lpfc_sli_ringtx_get(struct lpfc_hba *, | |||
416 | int __lpfc_sli_issue_iocb(struct lpfc_hba *, uint32_t, | 416 | int __lpfc_sli_issue_iocb(struct lpfc_hba *, uint32_t, |
417 | struct lpfc_iocbq *, uint32_t); | 417 | struct lpfc_iocbq *, uint32_t); |
418 | uint32_t lpfc_drain_txq(struct lpfc_hba *); | 418 | uint32_t lpfc_drain_txq(struct lpfc_hba *); |
419 | 419 | void lpfc_clr_rrq_active(struct lpfc_hba *, uint16_t, struct lpfc_node_rrq *); | |
420 | 420 | int lpfc_test_rrq_active(struct lpfc_hba *, struct lpfc_nodelist *, uint16_t); | |
421 | void lpfc_handle_rrq_active(struct lpfc_hba *); | ||
422 | int lpfc_send_rrq(struct lpfc_hba *, struct lpfc_node_rrq *); | ||
423 | int lpfc_set_rrq_active(struct lpfc_hba *, struct lpfc_nodelist *, | ||
424 | uint16_t, uint16_t, uint16_t); | ||
425 | void lpfc_cleanup_wt_rrqs(struct lpfc_hba *); | ||
426 | void lpfc_cleanup_vports_rrqs(struct lpfc_vport *); | ||
427 | struct lpfc_node_rrq *lpfc_get_active_rrq(struct lpfc_vport *, uint16_t, | ||
428 | uint32_t); | ||
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h index 7cae69de36f7..2f73252d15f0 100644 --- a/drivers/scsi/lpfc/lpfc_disc.h +++ b/drivers/scsi/lpfc/lpfc_disc.h | |||
@@ -68,6 +68,12 @@ struct lpfc_fast_path_event { | |||
68 | } un; | 68 | } un; |
69 | }; | 69 | }; |
70 | 70 | ||
71 | #define LPFC_SLI4_MAX_XRI 1024 /* Used to make the ndlp's xri_bitmap */ | ||
72 | #define XRI_BITMAP_ULONGS (LPFC_SLI4_MAX_XRI / BITS_PER_LONG) | ||
73 | struct lpfc_node_rrqs { | ||
74 | unsigned long xri_bitmap[XRI_BITMAP_ULONGS]; | ||
75 | }; | ||
76 | |||
71 | struct lpfc_nodelist { | 77 | struct lpfc_nodelist { |
72 | struct list_head nlp_listp; | 78 | struct list_head nlp_listp; |
73 | struct lpfc_name nlp_portname; | 79 | struct lpfc_name nlp_portname; |
@@ -110,8 +116,19 @@ struct lpfc_nodelist { | |||
110 | atomic_t cmd_pending; | 116 | atomic_t cmd_pending; |
111 | uint32_t cmd_qdepth; | 117 | uint32_t cmd_qdepth; |
112 | unsigned long last_change_time; | 118 | unsigned long last_change_time; |
119 | struct lpfc_node_rrqs active_rrqs; | ||
113 | struct lpfc_scsicmd_bkt *lat_data; /* Latency data */ | 120 | struct lpfc_scsicmd_bkt *lat_data; /* Latency data */ |
114 | }; | 121 | }; |
122 | struct lpfc_node_rrq { | ||
123 | struct list_head list; | ||
124 | uint16_t xritag; | ||
125 | uint16_t send_rrq; | ||
126 | uint16_t rxid; | ||
127 | uint32_t nlp_DID; /* FC D_ID of entry */ | ||
128 | struct lpfc_vport *vport; | ||
129 | struct lpfc_nodelist *ndlp; | ||
130 | unsigned long rrq_stop_time; | ||
131 | }; | ||
115 | 132 | ||
116 | /* Defines for nlp_flag (uint32) */ | 133 | /* Defines for nlp_flag (uint32) */ |
117 | #define NLP_IGNR_REG_CMPL 0x00000001 /* Rcvd rscn before we cmpl reg login */ | 134 | #define NLP_IGNR_REG_CMPL 0x00000001 /* Rcvd rscn before we cmpl reg login */ |
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 04072ce9c905..0705ad86538f 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -1290,6 +1290,7 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, | |||
1290 | uint32_t rc, keepDID = 0; | 1290 | uint32_t rc, keepDID = 0; |
1291 | int put_node; | 1291 | int put_node; |
1292 | int put_rport; | 1292 | int put_rport; |
1293 | struct lpfc_node_rrqs rrq; | ||
1293 | 1294 | ||
1294 | /* Fabric nodes can have the same WWPN so we don't bother searching | 1295 | /* Fabric nodes can have the same WWPN so we don't bother searching |
1295 | * by WWPN. Just return the ndlp that was given to us. | 1296 | * by WWPN. Just return the ndlp that was given to us. |
@@ -1307,6 +1308,7 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, | |||
1307 | 1308 | ||
1308 | if (new_ndlp == ndlp && NLP_CHK_NODE_ACT(new_ndlp)) | 1309 | if (new_ndlp == ndlp && NLP_CHK_NODE_ACT(new_ndlp)) |
1309 | return ndlp; | 1310 | return ndlp; |
1311 | memset(&rrq.xri_bitmap, 0, sizeof(new_ndlp->active_rrqs.xri_bitmap)); | ||
1310 | 1312 | ||
1311 | if (!new_ndlp) { | 1313 | if (!new_ndlp) { |
1312 | rc = memcmp(&ndlp->nlp_portname, name, | 1314 | rc = memcmp(&ndlp->nlp_portname, name, |
@@ -1327,12 +1329,25 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, | |||
1327 | if (!new_ndlp) | 1329 | if (!new_ndlp) |
1328 | return ndlp; | 1330 | return ndlp; |
1329 | keepDID = new_ndlp->nlp_DID; | 1331 | keepDID = new_ndlp->nlp_DID; |
1330 | } else | 1332 | if (phba->sli_rev == LPFC_SLI_REV4) |
1333 | memcpy(&rrq.xri_bitmap, | ||
1334 | &new_ndlp->active_rrqs.xri_bitmap, | ||
1335 | sizeof(new_ndlp->active_rrqs.xri_bitmap)); | ||
1336 | } else { | ||
1331 | keepDID = new_ndlp->nlp_DID; | 1337 | keepDID = new_ndlp->nlp_DID; |
1338 | if (phba->sli_rev == LPFC_SLI_REV4) | ||
1339 | memcpy(&rrq.xri_bitmap, | ||
1340 | &new_ndlp->active_rrqs.xri_bitmap, | ||
1341 | sizeof(new_ndlp->active_rrqs.xri_bitmap)); | ||
1342 | } | ||
1332 | 1343 | ||
1333 | lpfc_unreg_rpi(vport, new_ndlp); | 1344 | lpfc_unreg_rpi(vport, new_ndlp); |
1334 | new_ndlp->nlp_DID = ndlp->nlp_DID; | 1345 | new_ndlp->nlp_DID = ndlp->nlp_DID; |
1335 | new_ndlp->nlp_prev_state = ndlp->nlp_prev_state; | 1346 | new_ndlp->nlp_prev_state = ndlp->nlp_prev_state; |
1347 | if (phba->sli_rev == LPFC_SLI_REV4) | ||
1348 | memcpy(new_ndlp->active_rrqs.xri_bitmap, | ||
1349 | &ndlp->active_rrqs.xri_bitmap, | ||
1350 | sizeof(ndlp->active_rrqs.xri_bitmap)); | ||
1336 | 1351 | ||
1337 | if (ndlp->nlp_flag & NLP_NPR_2B_DISC) | 1352 | if (ndlp->nlp_flag & NLP_NPR_2B_DISC) |
1338 | new_ndlp->nlp_flag |= NLP_NPR_2B_DISC; | 1353 | new_ndlp->nlp_flag |= NLP_NPR_2B_DISC; |
@@ -1371,12 +1386,20 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, | |||
1371 | 1386 | ||
1372 | /* Two ndlps cannot have the same did on the nodelist */ | 1387 | /* Two ndlps cannot have the same did on the nodelist */ |
1373 | ndlp->nlp_DID = keepDID; | 1388 | ndlp->nlp_DID = keepDID; |
1389 | if (phba->sli_rev == LPFC_SLI_REV4) | ||
1390 | memcpy(&ndlp->active_rrqs.xri_bitmap, | ||
1391 | &rrq.xri_bitmap, | ||
1392 | sizeof(ndlp->active_rrqs.xri_bitmap)); | ||
1374 | lpfc_drop_node(vport, ndlp); | 1393 | lpfc_drop_node(vport, ndlp); |
1375 | } | 1394 | } |
1376 | else { | 1395 | else { |
1377 | lpfc_unreg_rpi(vport, ndlp); | 1396 | lpfc_unreg_rpi(vport, ndlp); |
1378 | /* Two ndlps cannot have the same did */ | 1397 | /* Two ndlps cannot have the same did */ |
1379 | ndlp->nlp_DID = keepDID; | 1398 | ndlp->nlp_DID = keepDID; |
1399 | if (phba->sli_rev == LPFC_SLI_REV4) | ||
1400 | memcpy(&ndlp->active_rrqs.xri_bitmap, | ||
1401 | &rrq.xri_bitmap, | ||
1402 | sizeof(ndlp->active_rrqs.xri_bitmap)); | ||
1380 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); | 1403 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); |
1381 | /* Since we are swapping the ndlp passed in with the new one | 1404 | /* Since we are swapping the ndlp passed in with the new one |
1382 | * and the did has already been swapped, copy over the | 1405 | * and the did has already been swapped, copy over the |
@@ -1437,6 +1460,73 @@ lpfc_end_rscn(struct lpfc_vport *vport) | |||
1437 | } | 1460 | } |
1438 | 1461 | ||
1439 | /** | 1462 | /** |
1463 | * lpfc_cmpl_els_rrq - Completion handled for els RRQs. | ||
1464 | * @phba: pointer to lpfc hba data structure. | ||
1465 | * @cmdiocb: pointer to lpfc command iocb data structure. | ||
1466 | * @rspiocb: pointer to lpfc response iocb data structure. | ||
1467 | * | ||
1468 | * This routine will call the clear rrq function to free the rrq and | ||
1469 | * clear the xri's bit in the ndlp's xri_bitmap. If the ndlp does not | ||
1470 | * exist then the clear_rrq is still called because the rrq needs to | ||
1471 | * be freed. | ||
1472 | **/ | ||
1473 | |||
1474 | static void | ||
1475 | lpfc_cmpl_els_rrq(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | ||
1476 | struct lpfc_iocbq *rspiocb) | ||
1477 | { | ||
1478 | struct lpfc_vport *vport = cmdiocb->vport; | ||
1479 | IOCB_t *irsp; | ||
1480 | struct lpfc_nodelist *ndlp; | ||
1481 | struct lpfc_node_rrq *rrq; | ||
1482 | |||
1483 | /* we pass cmdiocb to state machine which needs rspiocb as well */ | ||
1484 | rrq = cmdiocb->context_un.rrq; | ||
1485 | cmdiocb->context_un.rsp_iocb = rspiocb; | ||
1486 | |||
1487 | irsp = &rspiocb->iocb; | ||
1488 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | ||
1489 | "RRQ cmpl: status:x%x/x%x did:x%x", | ||
1490 | irsp->ulpStatus, irsp->un.ulpWord[4], | ||
1491 | irsp->un.elsreq64.remoteID); | ||
1492 | |||
1493 | ndlp = lpfc_findnode_did(vport, irsp->un.elsreq64.remoteID); | ||
1494 | if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) || ndlp != rrq->ndlp) { | ||
1495 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, | ||
1496 | "2882 RRQ completes to NPort x%x " | ||
1497 | "with no ndlp. Data: x%x x%x x%x\n", | ||
1498 | irsp->un.elsreq64.remoteID, | ||
1499 | irsp->ulpStatus, irsp->un.ulpWord[4], | ||
1500 | irsp->ulpIoTag); | ||
1501 | goto out; | ||
1502 | } | ||
1503 | |||
1504 | /* rrq completes to NPort <nlp_DID> */ | ||
1505 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | ||
1506 | "2880 RRQ completes to NPort x%x " | ||
1507 | "Data: x%x x%x x%x x%x x%x\n", | ||
1508 | ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4], | ||
1509 | irsp->ulpTimeout, rrq->xritag, rrq->rxid); | ||
1510 | |||
1511 | if (irsp->ulpStatus) { | ||
1512 | /* Check for retry */ | ||
1513 | /* RRQ failed Don't print the vport to vport rjts */ | ||
1514 | if (irsp->ulpStatus != IOSTAT_LS_RJT || | ||
1515 | (((irsp->un.ulpWord[4]) >> 16 != LSRJT_INVALID_CMD) && | ||
1516 | ((irsp->un.ulpWord[4]) >> 16 != LSRJT_UNABLE_TPC)) || | ||
1517 | (phba)->pport->cfg_log_verbose & LOG_ELS) | ||
1518 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, | ||
1519 | "2881 RRQ failure DID:%06X Status:x%x/x%x\n", | ||
1520 | ndlp->nlp_DID, irsp->ulpStatus, | ||
1521 | irsp->un.ulpWord[4]); | ||
1522 | } | ||
1523 | out: | ||
1524 | if (rrq) | ||
1525 | lpfc_clr_rrq_active(phba, rrq->xritag, rrq); | ||
1526 | lpfc_els_free_iocb(phba, cmdiocb); | ||
1527 | return; | ||
1528 | } | ||
1529 | /** | ||
1440 | * lpfc_cmpl_els_plogi - Completion callback function for plogi | 1530 | * lpfc_cmpl_els_plogi - Completion callback function for plogi |
1441 | * @phba: pointer to lpfc hba data structure. | 1531 | * @phba: pointer to lpfc hba data structure. |
1442 | * @cmdiocb: pointer to lpfc command iocb data structure. | 1532 | * @cmdiocb: pointer to lpfc command iocb data structure. |
@@ -3913,6 +4003,47 @@ lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format, | |||
3913 | } | 4003 | } |
3914 | 4004 | ||
3915 | /** | 4005 | /** |
4006 | * lpfc_els_clear_rrq - Clear the rq that this rrq describes. | ||
4007 | * @vport: pointer to a virtual N_Port data structure. | ||
4008 | * @iocb: pointer to the lpfc command iocb data structure. | ||
4009 | * @ndlp: pointer to a node-list data structure. | ||
4010 | * | ||
4011 | * Return | ||
4012 | **/ | ||
4013 | static void | ||
4014 | lpfc_els_clear_rrq(struct lpfc_vport *vport, | ||
4015 | struct lpfc_iocbq *iocb, struct lpfc_nodelist *ndlp) | ||
4016 | { | ||
4017 | struct lpfc_hba *phba = vport->phba; | ||
4018 | uint8_t *pcmd; | ||
4019 | struct RRQ *rrq; | ||
4020 | uint16_t rxid; | ||
4021 | struct lpfc_node_rrq *prrq; | ||
4022 | |||
4023 | |||
4024 | pcmd = (uint8_t *) (((struct lpfc_dmabuf *) iocb->context2)->virt); | ||
4025 | pcmd += sizeof(uint32_t); | ||
4026 | rrq = (struct RRQ *)pcmd; | ||
4027 | rxid = bf_get(rrq_oxid, rrq); | ||
4028 | |||
4029 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | ||
4030 | "2883 Clear RRQ for SID:x%x OXID:x%x RXID:x%x" | ||
4031 | " x%x x%x\n", | ||
4032 | bf_get(rrq_did, rrq), | ||
4033 | bf_get(rrq_oxid, rrq), | ||
4034 | rxid, | ||
4035 | iocb->iotag, iocb->iocb.ulpContext); | ||
4036 | |||
4037 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, | ||
4038 | "Clear RRQ: did:x%x flg:x%x exchg:x%.08x", | ||
4039 | ndlp->nlp_DID, ndlp->nlp_flag, rrq->rrq_exchg); | ||
4040 | prrq = lpfc_get_active_rrq(vport, rxid, ndlp->nlp_DID); | ||
4041 | if (prrq) | ||
4042 | lpfc_clr_rrq_active(phba, rxid, prrq); | ||
4043 | return; | ||
4044 | } | ||
4045 | |||
4046 | /** | ||
3916 | * lpfc_els_rsp_echo_acc - Issue echo acc response | 4047 | * lpfc_els_rsp_echo_acc - Issue echo acc response |
3917 | * @vport: pointer to a virtual N_Port data structure. | 4048 | * @vport: pointer to a virtual N_Port data structure. |
3918 | * @data: pointer to echo data to return in the accept. | 4049 | * @data: pointer to echo data to return in the accept. |
@@ -4801,6 +4932,8 @@ lpfc_els_rcv_rrq(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
4801 | struct lpfc_nodelist *ndlp) | 4932 | struct lpfc_nodelist *ndlp) |
4802 | { | 4933 | { |
4803 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); | 4934 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); |
4935 | if (vport->phba->sli_rev == LPFC_SLI_REV4) | ||
4936 | lpfc_els_clear_rrq(vport, cmdiocb, ndlp); | ||
4804 | } | 4937 | } |
4805 | 4938 | ||
4806 | /** | 4939 | /** |
@@ -5203,6 +5336,97 @@ reject_out: | |||
5203 | return 0; | 5336 | return 0; |
5204 | } | 5337 | } |
5205 | 5338 | ||
5339 | /* lpfc_issue_els_rrq - Process an unsolicited rps iocb | ||
5340 | * @vport: pointer to a host virtual N_Port data structure. | ||
5341 | * @ndlp: pointer to a node-list data structure. | ||
5342 | * @did: DID of the target. | ||
5343 | * @rrq: Pointer to the rrq struct. | ||
5344 | * | ||
5345 | * Build a ELS RRQ command and send it to the target. If the issue_iocb is | ||
5346 | * Successful the the completion handler will clear the RRQ. | ||
5347 | * | ||
5348 | * Return codes | ||
5349 | * 0 - Successfully sent rrq els iocb. | ||
5350 | * 1 - Failed to send rrq els iocb. | ||
5351 | **/ | ||
5352 | static int | ||
5353 | lpfc_issue_els_rrq(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | ||
5354 | uint32_t did, struct lpfc_node_rrq *rrq) | ||
5355 | { | ||
5356 | struct lpfc_hba *phba = vport->phba; | ||
5357 | struct RRQ *els_rrq; | ||
5358 | IOCB_t *icmd; | ||
5359 | struct lpfc_iocbq *elsiocb; | ||
5360 | uint8_t *pcmd; | ||
5361 | uint16_t cmdsize; | ||
5362 | int ret; | ||
5363 | |||
5364 | |||
5365 | if (ndlp != rrq->ndlp) | ||
5366 | ndlp = rrq->ndlp; | ||
5367 | if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) | ||
5368 | return 1; | ||
5369 | |||
5370 | /* If ndlp is not NULL, we will bump the reference count on it */ | ||
5371 | cmdsize = (sizeof(uint32_t) + sizeof(struct RRQ)); | ||
5372 | elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, 0, ndlp, did, | ||
5373 | ELS_CMD_RRQ); | ||
5374 | if (!elsiocb) | ||
5375 | return 1; | ||
5376 | |||
5377 | icmd = &elsiocb->iocb; | ||
5378 | pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); | ||
5379 | |||
5380 | /* For RRQ request, remainder of payload is Exchange IDs */ | ||
5381 | *((uint32_t *) (pcmd)) = ELS_CMD_RRQ; | ||
5382 | pcmd += sizeof(uint32_t); | ||
5383 | els_rrq = (struct RRQ *) pcmd; | ||
5384 | |||
5385 | bf_set(rrq_oxid, els_rrq, rrq->xritag); | ||
5386 | bf_set(rrq_rxid, els_rrq, rrq->rxid); | ||
5387 | bf_set(rrq_did, els_rrq, vport->fc_myDID); | ||
5388 | els_rrq->rrq = cpu_to_be32(els_rrq->rrq); | ||
5389 | els_rrq->rrq_exchg = cpu_to_be32(els_rrq->rrq_exchg); | ||
5390 | |||
5391 | |||
5392 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | ||
5393 | "Issue RRQ: did:x%x", | ||
5394 | did, rrq->xritag, rrq->rxid); | ||
5395 | elsiocb->context_un.rrq = rrq; | ||
5396 | elsiocb->iocb_cmpl = lpfc_cmpl_els_rrq; | ||
5397 | ret = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); | ||
5398 | |||
5399 | if (ret == IOCB_ERROR) { | ||
5400 | lpfc_els_free_iocb(phba, elsiocb); | ||
5401 | return 1; | ||
5402 | } | ||
5403 | return 0; | ||
5404 | } | ||
5405 | |||
5406 | /** | ||
5407 | * lpfc_send_rrq - Sends ELS RRQ if needed. | ||
5408 | * @phba: pointer to lpfc hba data structure. | ||
5409 | * @rrq: pointer to the active rrq. | ||
5410 | * | ||
5411 | * This routine will call the lpfc_issue_els_rrq if the rrq is | ||
5412 | * still active for the xri. If this function returns a failure then | ||
5413 | * the caller needs to clean up the RRQ by calling lpfc_clr_active_rrq. | ||
5414 | * | ||
5415 | * Returns 0 Success. | ||
5416 | * 1 Failure. | ||
5417 | **/ | ||
5418 | int | ||
5419 | lpfc_send_rrq(struct lpfc_hba *phba, struct lpfc_node_rrq *rrq) | ||
5420 | { | ||
5421 | struct lpfc_nodelist *ndlp = lpfc_findnode_did(rrq->vport, | ||
5422 | rrq->nlp_DID); | ||
5423 | if (lpfc_test_rrq_active(phba, ndlp, rrq->xritag)) | ||
5424 | return lpfc_issue_els_rrq(rrq->vport, ndlp, | ||
5425 | rrq->nlp_DID, rrq); | ||
5426 | else | ||
5427 | return 1; | ||
5428 | } | ||
5429 | |||
5206 | /** | 5430 | /** |
5207 | * lpfc_els_rsp_rpl_acc - Issue an accept rpl els command | 5431 | * lpfc_els_rsp_rpl_acc - Issue an accept rpl els command |
5208 | * @vport: pointer to a host virtual N_Port data structure. | 5432 | * @vport: pointer to a host virtual N_Port data structure. |
@@ -7373,8 +7597,11 @@ lpfc_sli4_els_xri_aborted(struct lpfc_hba *phba, | |||
7373 | struct sli4_wcqe_xri_aborted *axri) | 7597 | struct sli4_wcqe_xri_aborted *axri) |
7374 | { | 7598 | { |
7375 | uint16_t xri = bf_get(lpfc_wcqe_xa_xri, axri); | 7599 | uint16_t xri = bf_get(lpfc_wcqe_xa_xri, axri); |
7600 | uint16_t rxid = bf_get(lpfc_wcqe_xa_remote_xid, axri); | ||
7601 | |||
7376 | struct lpfc_sglq *sglq_entry = NULL, *sglq_next = NULL; | 7602 | struct lpfc_sglq *sglq_entry = NULL, *sglq_next = NULL; |
7377 | unsigned long iflag = 0; | 7603 | unsigned long iflag = 0; |
7604 | struct lpfc_nodelist *ndlp; | ||
7378 | struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; | 7605 | struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; |
7379 | 7606 | ||
7380 | spin_lock_irqsave(&phba->hbalock, iflag); | 7607 | spin_lock_irqsave(&phba->hbalock, iflag); |
@@ -7383,11 +7610,14 @@ lpfc_sli4_els_xri_aborted(struct lpfc_hba *phba, | |||
7383 | &phba->sli4_hba.lpfc_abts_els_sgl_list, list) { | 7610 | &phba->sli4_hba.lpfc_abts_els_sgl_list, list) { |
7384 | if (sglq_entry->sli4_xritag == xri) { | 7611 | if (sglq_entry->sli4_xritag == xri) { |
7385 | list_del(&sglq_entry->list); | 7612 | list_del(&sglq_entry->list); |
7613 | ndlp = sglq_entry->ndlp; | ||
7614 | sglq_entry->ndlp = NULL; | ||
7386 | list_add_tail(&sglq_entry->list, | 7615 | list_add_tail(&sglq_entry->list, |
7387 | &phba->sli4_hba.lpfc_sgl_list); | 7616 | &phba->sli4_hba.lpfc_sgl_list); |
7388 | sglq_entry->state = SGL_FREED; | 7617 | sglq_entry->state = SGL_FREED; |
7389 | spin_unlock(&phba->sli4_hba.abts_sgl_list_lock); | 7618 | spin_unlock(&phba->sli4_hba.abts_sgl_list_lock); |
7390 | spin_unlock_irqrestore(&phba->hbalock, iflag); | 7619 | spin_unlock_irqrestore(&phba->hbalock, iflag); |
7620 | lpfc_set_rrq_active(phba, ndlp, xri, rxid, 1); | ||
7391 | 7621 | ||
7392 | /* Check if TXQ queue needs to be serviced */ | 7622 | /* Check if TXQ queue needs to be serviced */ |
7393 | if (pring->txq_cnt) | 7623 | if (pring->txq_cnt) |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index e8d27c958510..91fa65906173 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -607,6 +607,8 @@ lpfc_work_done(struct lpfc_hba *phba) | |||
607 | 607 | ||
608 | /* Process SLI4 events */ | 608 | /* Process SLI4 events */ |
609 | if (phba->pci_dev_grp == LPFC_PCI_DEV_OC) { | 609 | if (phba->pci_dev_grp == LPFC_PCI_DEV_OC) { |
610 | if (phba->hba_flag & HBA_RRQ_ACTIVE) | ||
611 | lpfc_handle_rrq_active(phba); | ||
610 | if (phba->hba_flag & FCP_XRI_ABORT_EVENT) | 612 | if (phba->hba_flag & FCP_XRI_ABORT_EVENT) |
611 | lpfc_sli4_fcp_xri_abort_event_proc(phba); | 613 | lpfc_sli4_fcp_xri_abort_event_proc(phba); |
612 | if (phba->hba_flag & ELS_XRI_ABORT_EVENT) | 614 | if (phba->hba_flag & ELS_XRI_ABORT_EVENT) |
@@ -966,6 +968,7 @@ lpfc_linkup(struct lpfc_hba *phba) | |||
966 | struct lpfc_vport **vports; | 968 | struct lpfc_vport **vports; |
967 | int i; | 969 | int i; |
968 | 970 | ||
971 | lpfc_cleanup_wt_rrqs(phba); | ||
969 | phba->link_state = LPFC_LINK_UP; | 972 | phba->link_state = LPFC_LINK_UP; |
970 | 973 | ||
971 | /* Unblock fabric iocbs if they are blocked */ | 974 | /* Unblock fabric iocbs if they are blocked */ |
@@ -3161,6 +3164,7 @@ lpfc_mbx_cmpl_unreg_vpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
3161 | spin_unlock_irq(shost->host_lock); | 3164 | spin_unlock_irq(shost->host_lock); |
3162 | vport->unreg_vpi_cmpl = VPORT_OK; | 3165 | vport->unreg_vpi_cmpl = VPORT_OK; |
3163 | mempool_free(pmb, phba->mbox_mem_pool); | 3166 | mempool_free(pmb, phba->mbox_mem_pool); |
3167 | lpfc_cleanup_vports_rrqs(vport); | ||
3164 | /* | 3168 | /* |
3165 | * This shost reference might have been taken at the beginning of | 3169 | * This shost reference might have been taken at the beginning of |
3166 | * lpfc_vport_delete() | 3170 | * lpfc_vport_delete() |
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index a253216e1f18..96ed3ba6ba95 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h | |||
@@ -880,6 +880,24 @@ struct RLS_RSP { /* Structure is in Big Endian format */ | |||
880 | uint32_t crcCnt; | 880 | uint32_t crcCnt; |
881 | }; | 881 | }; |
882 | 882 | ||
883 | struct RRQ { /* Structure is in Big Endian format */ | ||
884 | uint32_t rrq; | ||
885 | #define rrq_rsvd_SHIFT 24 | ||
886 | #define rrq_rsvd_MASK 0x000000ff | ||
887 | #define rrq_rsvd_WORD rrq | ||
888 | #define rrq_did_SHIFT 0 | ||
889 | #define rrq_did_MASK 0x00ffffff | ||
890 | #define rrq_did_WORD rrq | ||
891 | uint32_t rrq_exchg; | ||
892 | #define rrq_oxid_SHIFT 16 | ||
893 | #define rrq_oxid_MASK 0xffff | ||
894 | #define rrq_oxid_WORD rrq_exchg | ||
895 | #define rrq_rxid_SHIFT 0 | ||
896 | #define rrq_rxid_MASK 0xffff | ||
897 | #define rrq_rxid_WORD rrq_exchg | ||
898 | }; | ||
899 | |||
900 | |||
883 | struct RTV_RSP { /* Structure is in Big Endian format */ | 901 | struct RTV_RSP { /* Structure is in Big Endian format */ |
884 | uint32_t ratov; | 902 | uint32_t ratov; |
885 | uint32_t edtov; | 903 | uint32_t edtov; |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 432afc7db1cc..70ba1895b0a1 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -930,6 +930,35 @@ lpfc_hb_timeout(unsigned long ptr) | |||
930 | } | 930 | } |
931 | 931 | ||
932 | /** | 932 | /** |
933 | * lpfc_rrq_timeout - The RRQ-timer timeout handler | ||
934 | * @ptr: unsigned long holds the pointer to lpfc hba data structure. | ||
935 | * | ||
936 | * This is the RRQ-timer timeout handler registered to the lpfc driver. When | ||
937 | * this timer fires, a RRQ timeout event shall be posted to the lpfc driver | ||
938 | * work-port-events bitmap and the worker thread is notified. This timeout | ||
939 | * event will be used by the worker thread to invoke the actual timeout | ||
940 | * handler routine, lpfc_rrq_handler. Any periodical operations will | ||
941 | * be performed in the timeout handler and the RRQ timeout event bit shall | ||
942 | * be cleared by the worker thread after it has taken the event bitmap out. | ||
943 | **/ | ||
944 | static void | ||
945 | lpfc_rrq_timeout(unsigned long ptr) | ||
946 | { | ||
947 | struct lpfc_hba *phba; | ||
948 | uint32_t tmo_posted; | ||
949 | unsigned long iflag; | ||
950 | |||
951 | phba = (struct lpfc_hba *)ptr; | ||
952 | spin_lock_irqsave(&phba->pport->work_port_lock, iflag); | ||
953 | tmo_posted = phba->hba_flag & HBA_RRQ_ACTIVE; | ||
954 | if (!tmo_posted) | ||
955 | phba->hba_flag |= HBA_RRQ_ACTIVE; | ||
956 | spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag); | ||
957 | if (!tmo_posted) | ||
958 | lpfc_worker_wake_up(phba); | ||
959 | } | ||
960 | |||
961 | /** | ||
933 | * lpfc_hb_mbox_cmpl - The lpfc heart-beat mailbox command callback function | 962 | * lpfc_hb_mbox_cmpl - The lpfc heart-beat mailbox command callback function |
934 | * @phba: pointer to lpfc hba data structure. | 963 | * @phba: pointer to lpfc hba data structure. |
935 | * @pmboxq: pointer to the driver internal queue element for mailbox command. | 964 | * @pmboxq: pointer to the driver internal queue element for mailbox command. |
@@ -3990,6 +4019,9 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) | |||
3990 | init_timer(&phba->hb_tmofunc); | 4019 | init_timer(&phba->hb_tmofunc); |
3991 | phba->hb_tmofunc.function = lpfc_hb_timeout; | 4020 | phba->hb_tmofunc.function = lpfc_hb_timeout; |
3992 | phba->hb_tmofunc.data = (unsigned long)phba; | 4021 | phba->hb_tmofunc.data = (unsigned long)phba; |
4022 | init_timer(&phba->rrq_tmr); | ||
4023 | phba->rrq_tmr.function = lpfc_rrq_timeout; | ||
4024 | phba->rrq_tmr.data = (unsigned long)phba; | ||
3993 | 4025 | ||
3994 | psli = &phba->sli; | 4026 | psli = &phba->sli; |
3995 | /* MBOX heartbeat timer */ | 4027 | /* MBOX heartbeat timer */ |
@@ -8192,6 +8224,8 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
8192 | goto out_unset_driver_resource_s4; | 8224 | goto out_unset_driver_resource_s4; |
8193 | } | 8225 | } |
8194 | 8226 | ||
8227 | INIT_LIST_HEAD(&phba->active_rrq_list); | ||
8228 | |||
8195 | /* Set up common device driver resources */ | 8229 | /* Set up common device driver resources */ |
8196 | error = lpfc_setup_driver_resource_phase2(phba); | 8230 | error = lpfc_setup_driver_resource_phase2(phba); |
8197 | if (error) { | 8231 | if (error) { |
diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c index 8f879e477e9d..cbb48ee8b0bb 100644 --- a/drivers/scsi/lpfc/lpfc_mem.c +++ b/drivers/scsi/lpfc/lpfc_mem.c | |||
@@ -113,11 +113,16 @@ lpfc_mem_alloc(struct lpfc_hba *phba, int align) | |||
113 | goto fail_free_mbox_pool; | 113 | goto fail_free_mbox_pool; |
114 | 114 | ||
115 | if (phba->sli_rev == LPFC_SLI_REV4) { | 115 | if (phba->sli_rev == LPFC_SLI_REV4) { |
116 | phba->rrq_pool = | ||
117 | mempool_create_kmalloc_pool(LPFC_MEM_POOL_SIZE, | ||
118 | sizeof(struct lpfc_node_rrq)); | ||
119 | if (!phba->rrq_pool) | ||
120 | goto fail_free_nlp_mem_pool; | ||
116 | phba->lpfc_hrb_pool = pci_pool_create("lpfc_hrb_pool", | 121 | phba->lpfc_hrb_pool = pci_pool_create("lpfc_hrb_pool", |
117 | phba->pcidev, | 122 | phba->pcidev, |
118 | LPFC_HDR_BUF_SIZE, align, 0); | 123 | LPFC_HDR_BUF_SIZE, align, 0); |
119 | if (!phba->lpfc_hrb_pool) | 124 | if (!phba->lpfc_hrb_pool) |
120 | goto fail_free_nlp_mem_pool; | 125 | goto fail_free_rrq_mem_pool; |
121 | 126 | ||
122 | phba->lpfc_drb_pool = pci_pool_create("lpfc_drb_pool", | 127 | phba->lpfc_drb_pool = pci_pool_create("lpfc_drb_pool", |
123 | phba->pcidev, | 128 | phba->pcidev, |
@@ -147,6 +152,9 @@ lpfc_mem_alloc(struct lpfc_hba *phba, int align) | |||
147 | fail_free_hrb_pool: | 152 | fail_free_hrb_pool: |
148 | pci_pool_destroy(phba->lpfc_hrb_pool); | 153 | pci_pool_destroy(phba->lpfc_hrb_pool); |
149 | phba->lpfc_hrb_pool = NULL; | 154 | phba->lpfc_hrb_pool = NULL; |
155 | fail_free_rrq_mem_pool: | ||
156 | mempool_destroy(phba->rrq_pool); | ||
157 | phba->rrq_pool = NULL; | ||
150 | fail_free_nlp_mem_pool: | 158 | fail_free_nlp_mem_pool: |
151 | mempool_destroy(phba->nlp_mem_pool); | 159 | mempool_destroy(phba->nlp_mem_pool); |
152 | phba->nlp_mem_pool = NULL; | 160 | phba->nlp_mem_pool = NULL; |
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 581837b3c71a..c97751c95d77 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
@@ -621,10 +621,13 @@ lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba, | |||
621 | struct sli4_wcqe_xri_aborted *axri) | 621 | struct sli4_wcqe_xri_aborted *axri) |
622 | { | 622 | { |
623 | uint16_t xri = bf_get(lpfc_wcqe_xa_xri, axri); | 623 | uint16_t xri = bf_get(lpfc_wcqe_xa_xri, axri); |
624 | uint16_t rxid = bf_get(lpfc_wcqe_xa_remote_xid, axri); | ||
624 | struct lpfc_scsi_buf *psb, *next_psb; | 625 | struct lpfc_scsi_buf *psb, *next_psb; |
625 | unsigned long iflag = 0; | 626 | unsigned long iflag = 0; |
626 | struct lpfc_iocbq *iocbq; | 627 | struct lpfc_iocbq *iocbq; |
627 | int i; | 628 | int i; |
629 | struct lpfc_nodelist *ndlp; | ||
630 | int rrq_empty = 0; | ||
628 | struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; | 631 | struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; |
629 | 632 | ||
630 | spin_lock_irqsave(&phba->hbalock, iflag); | 633 | spin_lock_irqsave(&phba->hbalock, iflag); |
@@ -637,8 +640,14 @@ lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba, | |||
637 | psb->status = IOSTAT_SUCCESS; | 640 | psb->status = IOSTAT_SUCCESS; |
638 | spin_unlock( | 641 | spin_unlock( |
639 | &phba->sli4_hba.abts_scsi_buf_list_lock); | 642 | &phba->sli4_hba.abts_scsi_buf_list_lock); |
643 | ndlp = psb->rdata->pnode; | ||
644 | rrq_empty = list_empty(&phba->active_rrq_list); | ||
640 | spin_unlock_irqrestore(&phba->hbalock, iflag); | 645 | spin_unlock_irqrestore(&phba->hbalock, iflag); |
646 | if (ndlp) | ||
647 | lpfc_set_rrq_active(phba, ndlp, xri, rxid, 1); | ||
641 | lpfc_release_scsi_buf_s4(phba, psb); | 648 | lpfc_release_scsi_buf_s4(phba, psb); |
649 | if (rrq_empty) | ||
650 | lpfc_worker_wake_up(phba); | ||
642 | return; | 651 | return; |
643 | } | 652 | } |
644 | } | 653 | } |
@@ -914,7 +923,7 @@ lpfc_new_scsi_buf(struct lpfc_vport *vport, int num_to_alloc) | |||
914 | } | 923 | } |
915 | 924 | ||
916 | /** | 925 | /** |
917 | * lpfc_get_scsi_buf - Get a scsi buffer from lpfc_scsi_buf_list of the HBA | 926 | * lpfc_get_scsi_buf_s3 - Get a scsi buffer from lpfc_scsi_buf_list of the HBA |
918 | * @phba: The HBA for which this call is being executed. | 927 | * @phba: The HBA for which this call is being executed. |
919 | * | 928 | * |
920 | * This routine removes a scsi buffer from head of @phba lpfc_scsi_buf_list list | 929 | * This routine removes a scsi buffer from head of @phba lpfc_scsi_buf_list list |
@@ -925,7 +934,7 @@ lpfc_new_scsi_buf(struct lpfc_vport *vport, int num_to_alloc) | |||
925 | * Pointer to lpfc_scsi_buf - Success | 934 | * Pointer to lpfc_scsi_buf - Success |
926 | **/ | 935 | **/ |
927 | static struct lpfc_scsi_buf* | 936 | static struct lpfc_scsi_buf* |
928 | lpfc_get_scsi_buf(struct lpfc_hba * phba) | 937 | lpfc_get_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) |
929 | { | 938 | { |
930 | struct lpfc_scsi_buf * lpfc_cmd = NULL; | 939 | struct lpfc_scsi_buf * lpfc_cmd = NULL; |
931 | struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list; | 940 | struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list; |
@@ -941,6 +950,67 @@ lpfc_get_scsi_buf(struct lpfc_hba * phba) | |||
941 | spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag); | 950 | spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag); |
942 | return lpfc_cmd; | 951 | return lpfc_cmd; |
943 | } | 952 | } |
953 | /** | ||
954 | * lpfc_get_scsi_buf_s4 - Get a scsi buffer from lpfc_scsi_buf_list of the HBA | ||
955 | * @phba: The HBA for which this call is being executed. | ||
956 | * | ||
957 | * This routine removes a scsi buffer from head of @phba lpfc_scsi_buf_list list | ||
958 | * and returns to caller. | ||
959 | * | ||
960 | * Return codes: | ||
961 | * NULL - Error | ||
962 | * Pointer to lpfc_scsi_buf - Success | ||
963 | **/ | ||
964 | static struct lpfc_scsi_buf* | ||
965 | lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) | ||
966 | { | ||
967 | struct lpfc_scsi_buf *lpfc_cmd = NULL; | ||
968 | struct lpfc_scsi_buf *start_lpfc_cmd = NULL; | ||
969 | struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list; | ||
970 | unsigned long iflag = 0; | ||
971 | int found = 0; | ||
972 | |||
973 | spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag); | ||
974 | list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list); | ||
975 | spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag); | ||
976 | while (!found && lpfc_cmd) { | ||
977 | if (lpfc_test_rrq_active(phba, ndlp, | ||
978 | lpfc_cmd->cur_iocbq.sli4_xritag)) { | ||
979 | lpfc_release_scsi_buf_s4(phba, lpfc_cmd); | ||
980 | spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag); | ||
981 | list_remove_head(scsi_buf_list, lpfc_cmd, | ||
982 | struct lpfc_scsi_buf, list); | ||
983 | spin_unlock_irqrestore(&phba->scsi_buf_list_lock, | ||
984 | iflag); | ||
985 | if (lpfc_cmd == start_lpfc_cmd) { | ||
986 | lpfc_cmd = NULL; | ||
987 | break; | ||
988 | } else | ||
989 | continue; | ||
990 | } | ||
991 | found = 1; | ||
992 | lpfc_cmd->seg_cnt = 0; | ||
993 | lpfc_cmd->nonsg_phys = 0; | ||
994 | lpfc_cmd->prot_seg_cnt = 0; | ||
995 | } | ||
996 | return lpfc_cmd; | ||
997 | } | ||
998 | /** | ||
999 | * lpfc_get_scsi_buf - Get a scsi buffer from lpfc_scsi_buf_list of the HBA | ||
1000 | * @phba: The HBA for which this call is being executed. | ||
1001 | * | ||
1002 | * This routine removes a scsi buffer from head of @phba lpfc_scsi_buf_list list | ||
1003 | * and returns to caller. | ||
1004 | * | ||
1005 | * Return codes: | ||
1006 | * NULL - Error | ||
1007 | * Pointer to lpfc_scsi_buf - Success | ||
1008 | **/ | ||
1009 | static struct lpfc_scsi_buf* | ||
1010 | lpfc_get_scsi_buf(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) | ||
1011 | { | ||
1012 | return phba->lpfc_get_scsi_buf(phba, ndlp); | ||
1013 | } | ||
944 | 1014 | ||
945 | /** | 1015 | /** |
946 | * lpfc_release_scsi_buf - Return a scsi buffer back to hba scsi buf list | 1016 | * lpfc_release_scsi_buf - Return a scsi buffer back to hba scsi buf list |
@@ -2744,18 +2814,19 @@ lpfc_scsi_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) | |||
2744 | 2814 | ||
2745 | phba->lpfc_scsi_unprep_dma_buf = lpfc_scsi_unprep_dma_buf; | 2815 | phba->lpfc_scsi_unprep_dma_buf = lpfc_scsi_unprep_dma_buf; |
2746 | phba->lpfc_scsi_prep_cmnd = lpfc_scsi_prep_cmnd; | 2816 | phba->lpfc_scsi_prep_cmnd = lpfc_scsi_prep_cmnd; |
2747 | phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf; | ||
2748 | 2817 | ||
2749 | switch (dev_grp) { | 2818 | switch (dev_grp) { |
2750 | case LPFC_PCI_DEV_LP: | 2819 | case LPFC_PCI_DEV_LP: |
2751 | phba->lpfc_new_scsi_buf = lpfc_new_scsi_buf_s3; | 2820 | phba->lpfc_new_scsi_buf = lpfc_new_scsi_buf_s3; |
2752 | phba->lpfc_scsi_prep_dma_buf = lpfc_scsi_prep_dma_buf_s3; | 2821 | phba->lpfc_scsi_prep_dma_buf = lpfc_scsi_prep_dma_buf_s3; |
2753 | phba->lpfc_release_scsi_buf = lpfc_release_scsi_buf_s3; | 2822 | phba->lpfc_release_scsi_buf = lpfc_release_scsi_buf_s3; |
2823 | phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf_s3; | ||
2754 | break; | 2824 | break; |
2755 | case LPFC_PCI_DEV_OC: | 2825 | case LPFC_PCI_DEV_OC: |
2756 | phba->lpfc_new_scsi_buf = lpfc_new_scsi_buf_s4; | 2826 | phba->lpfc_new_scsi_buf = lpfc_new_scsi_buf_s4; |
2757 | phba->lpfc_scsi_prep_dma_buf = lpfc_scsi_prep_dma_buf_s4; | 2827 | phba->lpfc_scsi_prep_dma_buf = lpfc_scsi_prep_dma_buf_s4; |
2758 | phba->lpfc_release_scsi_buf = lpfc_release_scsi_buf_s4; | 2828 | phba->lpfc_release_scsi_buf = lpfc_release_scsi_buf_s4; |
2829 | phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf_s4; | ||
2759 | break; | 2830 | break; |
2760 | default: | 2831 | default: |
2761 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 2832 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, |
@@ -2764,7 +2835,6 @@ lpfc_scsi_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) | |||
2764 | return -ENODEV; | 2835 | return -ENODEV; |
2765 | break; | 2836 | break; |
2766 | } | 2837 | } |
2767 | phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf; | ||
2768 | phba->lpfc_rampdown_queue_depth = lpfc_rampdown_queue_depth; | 2838 | phba->lpfc_rampdown_queue_depth = lpfc_rampdown_queue_depth; |
2769 | phba->lpfc_scsi_cmd_iocb_cmpl = lpfc_scsi_cmd_iocb_cmpl; | 2839 | phba->lpfc_scsi_cmd_iocb_cmpl = lpfc_scsi_cmd_iocb_cmpl; |
2770 | return 0; | 2840 | return 0; |
@@ -2940,7 +3010,7 @@ lpfc_queuecommand_lck(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) | |||
2940 | if (atomic_read(&ndlp->cmd_pending) >= ndlp->cmd_qdepth) | 3010 | if (atomic_read(&ndlp->cmd_pending) >= ndlp->cmd_qdepth) |
2941 | goto out_host_busy; | 3011 | goto out_host_busy; |
2942 | 3012 | ||
2943 | lpfc_cmd = lpfc_get_scsi_buf(phba); | 3013 | lpfc_cmd = lpfc_get_scsi_buf(phba, ndlp); |
2944 | if (lpfc_cmd == NULL) { | 3014 | if (lpfc_cmd == NULL) { |
2945 | lpfc_rampdown_queue_depth(phba); | 3015 | lpfc_rampdown_queue_depth(phba); |
2946 | 3016 | ||
@@ -3239,7 +3309,7 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct lpfc_rport_data *rdata, | |||
3239 | if (!pnode || !NLP_CHK_NODE_ACT(pnode)) | 3309 | if (!pnode || !NLP_CHK_NODE_ACT(pnode)) |
3240 | return FAILED; | 3310 | return FAILED; |
3241 | 3311 | ||
3242 | lpfc_cmd = lpfc_get_scsi_buf(phba); | 3312 | lpfc_cmd = lpfc_get_scsi_buf(phba, rdata->pnode); |
3243 | if (lpfc_cmd == NULL) | 3313 | if (lpfc_cmd == NULL) |
3244 | return FAILED; | 3314 | return FAILED; |
3245 | lpfc_cmd->timeout = 60; | 3315 | lpfc_cmd->timeout = 60; |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index bedaa4e7cbf8..752601509549 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -513,8 +513,344 @@ __lpfc_get_active_sglq(struct lpfc_hba *phba, uint16_t xritag) | |||
513 | } | 513 | } |
514 | 514 | ||
515 | /** | 515 | /** |
516 | * __lpfc_set_rrq_active - set RRQ active bit in the ndlp's xri_bitmap. | ||
517 | * @phba: Pointer to HBA context object. | ||
518 | * @ndlp: nodelist pointer for this target. | ||
519 | * @xritag: xri used in this exchange. | ||
520 | * @rxid: Remote Exchange ID. | ||
521 | * @send_rrq: Flag used to determine if we should send rrq els cmd. | ||
522 | * | ||
523 | * This function is called with hbalock held. | ||
524 | * The active bit is set in the ndlp's active rrq xri_bitmap. Allocates an | ||
525 | * rrq struct and adds it to the active_rrq_list. | ||
526 | * | ||
527 | * returns 0 for rrq slot for this xri | ||
528 | * < 0 Were not able to get rrq mem or invalid parameter. | ||
529 | **/ | ||
530 | static int | ||
531 | __lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | ||
532 | uint16_t xritag, uint16_t rxid, uint16_t send_rrq) | ||
533 | { | ||
534 | uint16_t adj_xri; | ||
535 | struct lpfc_node_rrq *rrq; | ||
536 | int empty; | ||
537 | |||
538 | /* | ||
539 | * set the active bit even if there is no mem available. | ||
540 | */ | ||
541 | adj_xri = xritag - phba->sli4_hba.max_cfg_param.xri_base; | ||
542 | if (!ndlp) | ||
543 | return -EINVAL; | ||
544 | if (test_and_set_bit(adj_xri, ndlp->active_rrqs.xri_bitmap)) | ||
545 | return -EINVAL; | ||
546 | rrq = mempool_alloc(phba->rrq_pool, GFP_KERNEL); | ||
547 | if (rrq) { | ||
548 | rrq->send_rrq = send_rrq; | ||
549 | rrq->xritag = xritag; | ||
550 | rrq->rrq_stop_time = jiffies + HZ * (phba->fc_ratov + 1); | ||
551 | rrq->ndlp = ndlp; | ||
552 | rrq->nlp_DID = ndlp->nlp_DID; | ||
553 | rrq->vport = ndlp->vport; | ||
554 | rrq->rxid = rxid; | ||
555 | empty = list_empty(&phba->active_rrq_list); | ||
556 | if (phba->cfg_enable_rrq && send_rrq) | ||
557 | /* | ||
558 | * We need the xri before we can add this to the | ||
559 | * phba active rrq list. | ||
560 | */ | ||
561 | rrq->send_rrq = send_rrq; | ||
562 | else | ||
563 | rrq->send_rrq = 0; | ||
564 | list_add_tail(&rrq->list, &phba->active_rrq_list); | ||
565 | if (!(phba->hba_flag & HBA_RRQ_ACTIVE)) { | ||
566 | phba->hba_flag |= HBA_RRQ_ACTIVE; | ||
567 | if (empty) | ||
568 | lpfc_worker_wake_up(phba); | ||
569 | } | ||
570 | return 0; | ||
571 | } | ||
572 | return -ENOMEM; | ||
573 | } | ||
574 | |||
575 | /** | ||
576 | * __lpfc_clr_rrq_active - Clears RRQ active bit in xri_bitmap. | ||
577 | * @phba: Pointer to HBA context object. | ||
578 | * @xritag: xri used in this exchange. | ||
579 | * @rrq: The RRQ to be cleared. | ||
580 | * | ||
581 | * This function is called with hbalock held. This function | ||
582 | **/ | ||
583 | static void | ||
584 | __lpfc_clr_rrq_active(struct lpfc_hba *phba, | ||
585 | uint16_t xritag, | ||
586 | struct lpfc_node_rrq *rrq) | ||
587 | { | ||
588 | uint16_t adj_xri; | ||
589 | struct lpfc_nodelist *ndlp; | ||
590 | |||
591 | ndlp = lpfc_findnode_did(rrq->vport, rrq->nlp_DID); | ||
592 | |||
593 | /* The target DID could have been swapped (cable swap) | ||
594 | * we should use the ndlp from the findnode if it is | ||
595 | * available. | ||
596 | */ | ||
597 | if (!ndlp) | ||
598 | ndlp = rrq->ndlp; | ||
599 | |||
600 | adj_xri = xritag - phba->sli4_hba.max_cfg_param.xri_base; | ||
601 | if (test_and_clear_bit(adj_xri, ndlp->active_rrqs.xri_bitmap)) { | ||
602 | rrq->send_rrq = 0; | ||
603 | rrq->xritag = 0; | ||
604 | rrq->rrq_stop_time = 0; | ||
605 | } | ||
606 | mempool_free(rrq, phba->rrq_pool); | ||
607 | } | ||
608 | |||
609 | /** | ||
610 | * lpfc_handle_rrq_active - Checks if RRQ has waithed RATOV. | ||
611 | * @phba: Pointer to HBA context object. | ||
612 | * | ||
613 | * This function is called with hbalock held. This function | ||
614 | * Checks if stop_time (ratov from setting rrq active) has | ||
615 | * been reached, if it has and the send_rrq flag is set then | ||
616 | * it will call lpfc_send_rrq. If the send_rrq flag is not set | ||
617 | * then it will just call the routine to clear the rrq and | ||
618 | * free the rrq resource. | ||
619 | * The timer is set to the next rrq that is going to expire before | ||
620 | * leaving the routine. | ||
621 | * | ||
622 | **/ | ||
623 | void | ||
624 | lpfc_handle_rrq_active(struct lpfc_hba *phba) | ||
625 | { | ||
626 | struct lpfc_node_rrq *rrq; | ||
627 | struct lpfc_node_rrq *nextrrq; | ||
628 | unsigned long next_time; | ||
629 | unsigned long iflags; | ||
630 | |||
631 | spin_lock_irqsave(&phba->hbalock, iflags); | ||
632 | phba->hba_flag &= ~HBA_RRQ_ACTIVE; | ||
633 | next_time = jiffies + HZ * (phba->fc_ratov + 1); | ||
634 | list_for_each_entry_safe(rrq, nextrrq, | ||
635 | &phba->active_rrq_list, list) { | ||
636 | if (time_after(jiffies, rrq->rrq_stop_time)) { | ||
637 | list_del(&rrq->list); | ||
638 | if (!rrq->send_rrq) | ||
639 | /* this call will free the rrq */ | ||
640 | __lpfc_clr_rrq_active(phba, rrq->xritag, rrq); | ||
641 | else { | ||
642 | /* if we send the rrq then the completion handler | ||
643 | * will clear the bit in the xribitmap. | ||
644 | */ | ||
645 | spin_unlock_irqrestore(&phba->hbalock, iflags); | ||
646 | if (lpfc_send_rrq(phba, rrq)) { | ||
647 | lpfc_clr_rrq_active(phba, rrq->xritag, | ||
648 | rrq); | ||
649 | } | ||
650 | spin_lock_irqsave(&phba->hbalock, iflags); | ||
651 | } | ||
652 | } else if (time_before(rrq->rrq_stop_time, next_time)) | ||
653 | next_time = rrq->rrq_stop_time; | ||
654 | } | ||
655 | spin_unlock_irqrestore(&phba->hbalock, iflags); | ||
656 | if (!list_empty(&phba->active_rrq_list)) | ||
657 | mod_timer(&phba->rrq_tmr, next_time); | ||
658 | } | ||
659 | |||
660 | /** | ||
661 | * lpfc_get_active_rrq - Get the active RRQ for this exchange. | ||
662 | * @vport: Pointer to vport context object. | ||
663 | * @xri: The xri used in the exchange. | ||
664 | * @did: The targets DID for this exchange. | ||
665 | * | ||
666 | * returns NULL = rrq not found in the phba->active_rrq_list. | ||
667 | * rrq = rrq for this xri and target. | ||
668 | **/ | ||
669 | struct lpfc_node_rrq * | ||
670 | lpfc_get_active_rrq(struct lpfc_vport *vport, uint16_t xri, uint32_t did) | ||
671 | { | ||
672 | struct lpfc_hba *phba = vport->phba; | ||
673 | struct lpfc_node_rrq *rrq; | ||
674 | struct lpfc_node_rrq *nextrrq; | ||
675 | unsigned long iflags; | ||
676 | |||
677 | if (phba->sli_rev != LPFC_SLI_REV4) | ||
678 | return NULL; | ||
679 | spin_lock_irqsave(&phba->hbalock, iflags); | ||
680 | list_for_each_entry_safe(rrq, nextrrq, &phba->active_rrq_list, list) { | ||
681 | if (rrq->vport == vport && rrq->xritag == xri && | ||
682 | rrq->nlp_DID == did){ | ||
683 | list_del(&rrq->list); | ||
684 | spin_unlock_irqrestore(&phba->hbalock, iflags); | ||
685 | return rrq; | ||
686 | } | ||
687 | } | ||
688 | spin_unlock_irqrestore(&phba->hbalock, iflags); | ||
689 | return NULL; | ||
690 | } | ||
691 | |||
692 | /** | ||
693 | * lpfc_cleanup_vports_rrqs - Remove and clear the active RRQ for this vport. | ||
694 | * @vport: Pointer to vport context object. | ||
695 | * | ||
696 | * Remove all active RRQs for this vport from the phba->active_rrq_list and | ||
697 | * clear the rrq. | ||
698 | **/ | ||
699 | void | ||
700 | lpfc_cleanup_vports_rrqs(struct lpfc_vport *vport) | ||
701 | |||
702 | { | ||
703 | struct lpfc_hba *phba = vport->phba; | ||
704 | struct lpfc_node_rrq *rrq; | ||
705 | struct lpfc_node_rrq *nextrrq; | ||
706 | unsigned long iflags; | ||
707 | |||
708 | if (phba->sli_rev != LPFC_SLI_REV4) | ||
709 | return; | ||
710 | spin_lock_irqsave(&phba->hbalock, iflags); | ||
711 | list_for_each_entry_safe(rrq, nextrrq, &phba->active_rrq_list, list) { | ||
712 | if (rrq->vport == vport) { | ||
713 | list_del(&rrq->list); | ||
714 | __lpfc_clr_rrq_active(phba, rrq->xritag, rrq); | ||
715 | } | ||
716 | } | ||
717 | spin_unlock_irqrestore(&phba->hbalock, iflags); | ||
718 | } | ||
719 | |||
720 | /** | ||
721 | * lpfc_cleanup_wt_rrqs - Remove all rrq's from the active list. | ||
722 | * @phba: Pointer to HBA context object. | ||
723 | * | ||
724 | * Remove all rrqs from the phba->active_rrq_list and free them by | ||
725 | * calling __lpfc_clr_active_rrq | ||
726 | * | ||
727 | **/ | ||
728 | void | ||
729 | lpfc_cleanup_wt_rrqs(struct lpfc_hba *phba) | ||
730 | { | ||
731 | struct lpfc_node_rrq *rrq; | ||
732 | struct lpfc_node_rrq *nextrrq; | ||
733 | unsigned long next_time; | ||
734 | unsigned long iflags; | ||
735 | |||
736 | if (phba->sli_rev != LPFC_SLI_REV4) | ||
737 | return; | ||
738 | spin_lock_irqsave(&phba->hbalock, iflags); | ||
739 | phba->hba_flag &= ~HBA_RRQ_ACTIVE; | ||
740 | next_time = jiffies + HZ * (phba->fc_ratov * 2); | ||
741 | list_for_each_entry_safe(rrq, nextrrq, &phba->active_rrq_list, list) { | ||
742 | list_del(&rrq->list); | ||
743 | __lpfc_clr_rrq_active(phba, rrq->xritag, rrq); | ||
744 | } | ||
745 | spin_unlock_irqrestore(&phba->hbalock, iflags); | ||
746 | if (!list_empty(&phba->active_rrq_list)) | ||
747 | mod_timer(&phba->rrq_tmr, next_time); | ||
748 | } | ||
749 | |||
750 | |||
751 | /** | ||
752 | * __lpfc_test_rrq_active - Test RRQ bit in xri_bitmap. | ||
753 | * @phba: Pointer to HBA context object. | ||
754 | * @ndlp: Targets nodelist pointer for this exchange. | ||
755 | * @xritag the xri in the bitmap to test. | ||
756 | * | ||
757 | * This function is called with hbalock held. This function | ||
758 | * returns 0 = rrq not active for this xri | ||
759 | * 1 = rrq is valid for this xri. | ||
760 | **/ | ||
761 | static int | ||
762 | __lpfc_test_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | ||
763 | uint16_t xritag) | ||
764 | { | ||
765 | uint16_t adj_xri; | ||
766 | |||
767 | adj_xri = xritag - phba->sli4_hba.max_cfg_param.xri_base; | ||
768 | if (!ndlp) | ||
769 | return 0; | ||
770 | if (test_bit(adj_xri, ndlp->active_rrqs.xri_bitmap)) | ||
771 | return 1; | ||
772 | else | ||
773 | return 0; | ||
774 | } | ||
775 | |||
776 | /** | ||
777 | * lpfc_set_rrq_active - set RRQ active bit in xri_bitmap. | ||
778 | * @phba: Pointer to HBA context object. | ||
779 | * @ndlp: nodelist pointer for this target. | ||
780 | * @xritag: xri used in this exchange. | ||
781 | * @rxid: Remote Exchange ID. | ||
782 | * @send_rrq: Flag used to determine if we should send rrq els cmd. | ||
783 | * | ||
784 | * This function takes the hbalock. | ||
785 | * The active bit is always set in the active rrq xri_bitmap even | ||
786 | * if there is no slot avaiable for the other rrq information. | ||
787 | * | ||
788 | * returns 0 rrq actived for this xri | ||
789 | * < 0 No memory or invalid ndlp. | ||
790 | **/ | ||
791 | int | ||
792 | lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | ||
793 | uint16_t xritag, uint16_t rxid, uint16_t send_rrq) | ||
794 | { | ||
795 | int ret; | ||
796 | unsigned long iflags; | ||
797 | |||
798 | spin_lock_irqsave(&phba->hbalock, iflags); | ||
799 | ret = __lpfc_set_rrq_active(phba, ndlp, xritag, rxid, send_rrq); | ||
800 | spin_unlock_irqrestore(&phba->hbalock, iflags); | ||
801 | return ret; | ||
802 | } | ||
803 | |||
804 | /** | ||
805 | * lpfc_clr_rrq_active - Clears RRQ active bit in xri_bitmap. | ||
806 | * @phba: Pointer to HBA context object. | ||
807 | * @xritag: xri used in this exchange. | ||
808 | * @rrq: The RRQ to be cleared. | ||
809 | * | ||
810 | * This function is takes the hbalock. | ||
811 | **/ | ||
812 | void | ||
813 | lpfc_clr_rrq_active(struct lpfc_hba *phba, | ||
814 | uint16_t xritag, | ||
815 | struct lpfc_node_rrq *rrq) | ||
816 | { | ||
817 | unsigned long iflags; | ||
818 | |||
819 | spin_lock_irqsave(&phba->hbalock, iflags); | ||
820 | __lpfc_clr_rrq_active(phba, xritag, rrq); | ||
821 | spin_unlock_irqrestore(&phba->hbalock, iflags); | ||
822 | return; | ||
823 | } | ||
824 | |||
825 | |||
826 | |||
827 | /** | ||
828 | * lpfc_test_rrq_active - Test RRQ bit in xri_bitmap. | ||
829 | * @phba: Pointer to HBA context object. | ||
830 | * @ndlp: Targets nodelist pointer for this exchange. | ||
831 | * @xritag the xri in the bitmap to test. | ||
832 | * | ||
833 | * This function takes the hbalock. | ||
834 | * returns 0 = rrq not active for this xri | ||
835 | * 1 = rrq is valid for this xri. | ||
836 | **/ | ||
837 | int | ||
838 | lpfc_test_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | ||
839 | uint16_t xritag) | ||
840 | { | ||
841 | int ret; | ||
842 | unsigned long iflags; | ||
843 | |||
844 | spin_lock_irqsave(&phba->hbalock, iflags); | ||
845 | ret = __lpfc_test_rrq_active(phba, ndlp, xritag); | ||
846 | spin_unlock_irqrestore(&phba->hbalock, iflags); | ||
847 | return ret; | ||
848 | } | ||
849 | |||
850 | /** | ||
516 | * __lpfc_sli_get_sglq - Allocates an iocb object from sgl pool | 851 | * __lpfc_sli_get_sglq - Allocates an iocb object from sgl pool |
517 | * @phba: Pointer to HBA context object. | 852 | * @phba: Pointer to HBA context object. |
853 | * @piocb: Pointer to the iocbq. | ||
518 | * | 854 | * |
519 | * This function is called with hbalock held. This function | 855 | * This function is called with hbalock held. This function |
520 | * Gets a new driver sglq object from the sglq list. If the | 856 | * Gets a new driver sglq object from the sglq list. If the |
@@ -522,17 +858,53 @@ __lpfc_get_active_sglq(struct lpfc_hba *phba, uint16_t xritag) | |||
522 | * allocated sglq object else it returns NULL. | 858 | * allocated sglq object else it returns NULL. |
523 | **/ | 859 | **/ |
524 | static struct lpfc_sglq * | 860 | static struct lpfc_sglq * |
525 | __lpfc_sli_get_sglq(struct lpfc_hba *phba) | 861 | __lpfc_sli_get_sglq(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq) |
526 | { | 862 | { |
527 | struct list_head *lpfc_sgl_list = &phba->sli4_hba.lpfc_sgl_list; | 863 | struct list_head *lpfc_sgl_list = &phba->sli4_hba.lpfc_sgl_list; |
528 | struct lpfc_sglq *sglq = NULL; | 864 | struct lpfc_sglq *sglq = NULL; |
865 | struct lpfc_sglq *start_sglq = NULL; | ||
529 | uint16_t adj_xri; | 866 | uint16_t adj_xri; |
867 | struct lpfc_scsi_buf *lpfc_cmd; | ||
868 | struct lpfc_nodelist *ndlp; | ||
869 | int found = 0; | ||
870 | |||
871 | if (piocbq->iocb_flag & LPFC_IO_FCP) { | ||
872 | lpfc_cmd = (struct lpfc_scsi_buf *) piocbq->context1; | ||
873 | ndlp = lpfc_cmd->rdata->pnode; | ||
874 | } else if (piocbq->iocb.ulpCommand == CMD_GEN_REQUEST64_CR) | ||
875 | ndlp = piocbq->context_un.ndlp; | ||
876 | else if (piocbq->iocb.ulpCommand == CMD_XMIT_BLS_RSP64_CX) | ||
877 | ndlp = lpfc_findnode_did(piocbq->vport, | ||
878 | piocbq->iocb.ulpContext); | ||
879 | else | ||
880 | ndlp = piocbq->context1; | ||
881 | |||
530 | list_remove_head(lpfc_sgl_list, sglq, struct lpfc_sglq, list); | 882 | list_remove_head(lpfc_sgl_list, sglq, struct lpfc_sglq, list); |
531 | if (!sglq) | 883 | start_sglq = sglq; |
532 | return NULL; | 884 | while (!found) { |
533 | adj_xri = sglq->sli4_xritag - phba->sli4_hba.max_cfg_param.xri_base; | 885 | if (!sglq) |
534 | phba->sli4_hba.lpfc_sglq_active_list[adj_xri] = sglq; | 886 | return NULL; |
535 | sglq->state = SGL_ALLOCATED; | 887 | adj_xri = sglq->sli4_xritag - |
888 | phba->sli4_hba.max_cfg_param.xri_base; | ||
889 | if (__lpfc_test_rrq_active(phba, ndlp, sglq->sli4_xritag)) { | ||
890 | /* This xri has an rrq outstanding for this DID. | ||
891 | * put it back in the list and get another xri. | ||
892 | */ | ||
893 | list_add_tail(&sglq->list, lpfc_sgl_list); | ||
894 | sglq = NULL; | ||
895 | list_remove_head(lpfc_sgl_list, sglq, | ||
896 | struct lpfc_sglq, list); | ||
897 | if (sglq == start_sglq) { | ||
898 | sglq = NULL; | ||
899 | break; | ||
900 | } else | ||
901 | continue; | ||
902 | } | ||
903 | sglq->ndlp = ndlp; | ||
904 | found = 1; | ||
905 | phba->sli4_hba.lpfc_sglq_active_list[adj_xri] = sglq; | ||
906 | sglq->state = SGL_ALLOCATED; | ||
907 | } | ||
536 | return sglq; | 908 | return sglq; |
537 | } | 909 | } |
538 | 910 | ||
@@ -598,6 +970,7 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) | |||
598 | &phba->sli4_hba.abts_sgl_list_lock, iflag); | 970 | &phba->sli4_hba.abts_sgl_list_lock, iflag); |
599 | } else { | 971 | } else { |
600 | sglq->state = SGL_FREED; | 972 | sglq->state = SGL_FREED; |
973 | sglq->ndlp = NULL; | ||
601 | list_add(&sglq->list, &phba->sli4_hba.lpfc_sgl_list); | 974 | list_add(&sglq->list, &phba->sli4_hba.lpfc_sgl_list); |
602 | 975 | ||
603 | /* Check if TXQ queue needs to be serviced */ | 976 | /* Check if TXQ queue needs to be serviced */ |
@@ -6352,7 +6725,7 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, | |||
6352 | return IOCB_BUSY; | 6725 | return IOCB_BUSY; |
6353 | } | 6726 | } |
6354 | } else { | 6727 | } else { |
6355 | sglq = __lpfc_sli_get_sglq(phba); | 6728 | sglq = __lpfc_sli_get_sglq(phba, piocb); |
6356 | if (!sglq) { | 6729 | if (!sglq) { |
6357 | if (!(flag & SLI_IOCB_RET_IOCB)) { | 6730 | if (!(flag & SLI_IOCB_RET_IOCB)) { |
6358 | __lpfc_sli_ringtx_put(phba, | 6731 | __lpfc_sli_ringtx_put(phba, |
@@ -11570,6 +11943,10 @@ lpfc_sli4_seq_abort_acc(struct lpfc_hba *phba, | |||
11570 | "SID:x%x\n", oxid, sid); | 11943 | "SID:x%x\n", oxid, sid); |
11571 | return; | 11944 | return; |
11572 | } | 11945 | } |
11946 | if (rxid >= phba->sli4_hba.max_cfg_param.xri_base | ||
11947 | && rxid <= (phba->sli4_hba.max_cfg_param.max_xri | ||
11948 | + phba->sli4_hba.max_cfg_param.xri_base)) | ||
11949 | lpfc_set_rrq_active(phba, ndlp, rxid, oxid, 0); | ||
11573 | 11950 | ||
11574 | /* Allocate buffer for acc iocb */ | 11951 | /* Allocate buffer for acc iocb */ |
11575 | ctiocb = lpfc_sli_get_iocbq(phba); | 11952 | ctiocb = lpfc_sli_get_iocbq(phba); |
@@ -13008,12 +13385,13 @@ lpfc_drain_txq(struct lpfc_hba *phba) | |||
13008 | while (pring->txq_cnt) { | 13385 | while (pring->txq_cnt) { |
13009 | spin_lock_irqsave(&phba->hbalock, iflags); | 13386 | spin_lock_irqsave(&phba->hbalock, iflags); |
13010 | 13387 | ||
13011 | sglq = __lpfc_sli_get_sglq(phba); | 13388 | piocbq = lpfc_sli_ringtx_get(phba, pring); |
13389 | sglq = __lpfc_sli_get_sglq(phba, piocbq); | ||
13012 | if (!sglq) { | 13390 | if (!sglq) { |
13391 | __lpfc_sli_ringtx_put(phba, pring, piocbq); | ||
13013 | spin_unlock_irqrestore(&phba->hbalock, iflags); | 13392 | spin_unlock_irqrestore(&phba->hbalock, iflags); |
13014 | break; | 13393 | break; |
13015 | } else { | 13394 | } else { |
13016 | piocbq = lpfc_sli_ringtx_get(phba, pring); | ||
13017 | if (!piocbq) { | 13395 | if (!piocbq) { |
13018 | /* The txq_cnt out of sync. This should | 13396 | /* The txq_cnt out of sync. This should |
13019 | * never happen | 13397 | * never happen |
diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h index cd56d6cce6c3..402a0737076c 100644 --- a/drivers/scsi/lpfc/lpfc_sli.h +++ b/drivers/scsi/lpfc/lpfc_sli.h | |||
@@ -82,6 +82,7 @@ struct lpfc_iocbq { | |||
82 | struct lpfc_iocbq *rsp_iocb; | 82 | struct lpfc_iocbq *rsp_iocb; |
83 | struct lpfcMboxq *mbox; | 83 | struct lpfcMboxq *mbox; |
84 | struct lpfc_nodelist *ndlp; | 84 | struct lpfc_nodelist *ndlp; |
85 | struct lpfc_node_rrq *rrq; | ||
85 | } context_un; | 86 | } context_un; |
86 | 87 | ||
87 | void (*fabric_iocb_cmpl) (struct lpfc_hba *, struct lpfc_iocbq *, | 88 | void (*fabric_iocb_cmpl) (struct lpfc_hba *, struct lpfc_iocbq *, |
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index bc30fcf3f804..8ced5983d3e3 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h | |||
@@ -466,6 +466,7 @@ struct lpfc_sglq { | |||
466 | struct list_head clist; | 466 | struct list_head clist; |
467 | enum lpfc_sge_type buff_type; /* is this a scsi sgl */ | 467 | enum lpfc_sge_type buff_type; /* is this a scsi sgl */ |
468 | enum lpfc_sgl_state state; | 468 | enum lpfc_sgl_state state; |
469 | struct lpfc_nodelist *ndlp; /* ndlp associated with IO */ | ||
469 | uint16_t iotag; /* pre-assigned IO tag */ | 470 | uint16_t iotag; /* pre-assigned IO tag */ |
470 | uint16_t sli4_xritag; /* pre-assigned XRI, (OXID) tag. */ | 471 | uint16_t sli4_xritag; /* pre-assigned XRI, (OXID) tag. */ |
471 | struct sli4_sge *sgl; /* pre-assigned SGL */ | 472 | struct sli4_sge *sgl; /* pre-assigned SGL */ |