diff options
author | James Smart <james.smart@emulex.com> | 2013-12-17 20:29:47 -0500 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2014-03-15 13:18:55 -0400 |
commit | cff261f6bd03612e792e4c8872c6ad049f743863 (patch) | |
tree | ed71f93dfa4758bb71ff4e77f615133b4755bfaa | |
parent | 0976e1a650bdcdf235808e35c96eee70081c079d (diff) |
[SCSI] lpfc 8.3.44: Fix kernel panics from corrupted ndlp list
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_disc.h | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 80 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 21 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 3 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_mem.c | 22 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 11 |
8 files changed, 110 insertions, 32 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 4e1b75ca7451..4de95559c6b7 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
@@ -730,6 +730,7 @@ struct lpfc_hba { | |||
730 | uint32_t cfg_request_firmware_upgrade; | 730 | uint32_t cfg_request_firmware_upgrade; |
731 | uint32_t cfg_iocb_cnt; | 731 | uint32_t cfg_iocb_cnt; |
732 | uint32_t cfg_suppress_link_up; | 732 | uint32_t cfg_suppress_link_up; |
733 | uint32_t cfg_rrq_xri_bitmap_sz; | ||
733 | #define LPFC_INITIALIZE_LINK 0 /* do normal init_link mbox */ | 734 | #define LPFC_INITIALIZE_LINK 0 /* do normal init_link mbox */ |
734 | #define LPFC_DELAY_INIT_LINK 1 /* layered driver hold off */ | 735 | #define LPFC_DELAY_INIT_LINK 1 /* layered driver hold off */ |
735 | #define LPFC_DELAY_INIT_LINK_INDEFINITELY 2 /* wait, manual intervention */ | 736 | #define LPFC_DELAY_INIT_LINK_INDEFINITELY 2 /* wait, manual intervention */ |
@@ -835,6 +836,7 @@ struct lpfc_hba { | |||
835 | mempool_t *mbox_mem_pool; | 836 | mempool_t *mbox_mem_pool; |
836 | mempool_t *nlp_mem_pool; | 837 | mempool_t *nlp_mem_pool; |
837 | mempool_t *rrq_pool; | 838 | mempool_t *rrq_pool; |
839 | mempool_t *active_rrq_pool; | ||
838 | 840 | ||
839 | struct fc_host_statistics link_stats; | 841 | struct fc_host_statistics link_stats; |
840 | enum intr_type_t intr_type; | 842 | enum intr_type_t intr_type; |
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index cda076a84239..090945167d7c 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
@@ -242,6 +242,7 @@ int lpfc_sli4_fcf_rr_next_proc(struct lpfc_vport *, uint16_t); | |||
242 | void lpfc_sli4_clear_fcf_rr_bmask(struct lpfc_hba *); | 242 | void lpfc_sli4_clear_fcf_rr_bmask(struct lpfc_hba *); |
243 | 243 | ||
244 | int lpfc_mem_alloc(struct lpfc_hba *, int align); | 244 | int lpfc_mem_alloc(struct lpfc_hba *, int align); |
245 | int lpfc_mem_alloc_active_rrq_pool_s4(struct lpfc_hba *); | ||
245 | void lpfc_mem_free(struct lpfc_hba *); | 246 | void lpfc_mem_free(struct lpfc_hba *); |
246 | void lpfc_mem_free_all(struct lpfc_hba *); | 247 | void lpfc_mem_free_all(struct lpfc_hba *); |
247 | void lpfc_stop_vport_timers(struct lpfc_vport *); | 248 | void lpfc_stop_vport_timers(struct lpfc_vport *); |
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h index e409ba5f728c..1a6fe524940d 100644 --- a/drivers/scsi/lpfc/lpfc_disc.h +++ b/drivers/scsi/lpfc/lpfc_disc.h | |||
@@ -116,7 +116,7 @@ struct lpfc_nodelist { | |||
116 | atomic_t cmd_pending; | 116 | atomic_t cmd_pending; |
117 | uint32_t cmd_qdepth; | 117 | uint32_t cmd_qdepth; |
118 | unsigned long last_change_time; | 118 | unsigned long last_change_time; |
119 | struct lpfc_node_rrqs active_rrqs; | 119 | unsigned long *active_rrqs_xri_bitmap; |
120 | struct lpfc_scsicmd_bkt *lat_data; /* Latency data */ | 120 | struct lpfc_scsicmd_bkt *lat_data; /* Latency data */ |
121 | }; | 121 | }; |
122 | struct lpfc_node_rrq { | 122 | struct lpfc_node_rrq { |
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 647f4f3b3748..2b5e88df9ff9 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -1516,7 +1516,7 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, | |||
1516 | uint32_t rc, keepDID = 0; | 1516 | uint32_t rc, keepDID = 0; |
1517 | int put_node; | 1517 | int put_node; |
1518 | int put_rport; | 1518 | int put_rport; |
1519 | struct lpfc_node_rrqs rrq; | 1519 | unsigned long *active_rrqs_xri_bitmap = NULL; |
1520 | 1520 | ||
1521 | /* Fabric nodes can have the same WWPN so we don't bother searching | 1521 | /* Fabric nodes can have the same WWPN so we don't bother searching |
1522 | * by WWPN. Just return the ndlp that was given to us. | 1522 | * by WWPN. Just return the ndlp that was given to us. |
@@ -1534,7 +1534,13 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, | |||
1534 | 1534 | ||
1535 | if (new_ndlp == ndlp && NLP_CHK_NODE_ACT(new_ndlp)) | 1535 | if (new_ndlp == ndlp && NLP_CHK_NODE_ACT(new_ndlp)) |
1536 | return ndlp; | 1536 | return ndlp; |
1537 | memset(&rrq.xri_bitmap, 0, sizeof(new_ndlp->active_rrqs.xri_bitmap)); | 1537 | if (phba->sli_rev == LPFC_SLI_REV4) { |
1538 | active_rrqs_xri_bitmap = mempool_alloc(phba->active_rrq_pool, | ||
1539 | GFP_KERNEL); | ||
1540 | if (active_rrqs_xri_bitmap) | ||
1541 | memset(active_rrqs_xri_bitmap, 0, | ||
1542 | phba->cfg_rrq_xri_bitmap_sz); | ||
1543 | } | ||
1538 | 1544 | ||
1539 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | 1545 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
1540 | "3178 PLOGI confirm: ndlp %p x%x: new_ndlp %p\n", | 1546 | "3178 PLOGI confirm: ndlp %p x%x: new_ndlp %p\n", |
@@ -1543,41 +1549,58 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, | |||
1543 | if (!new_ndlp) { | 1549 | if (!new_ndlp) { |
1544 | rc = memcmp(&ndlp->nlp_portname, name, | 1550 | rc = memcmp(&ndlp->nlp_portname, name, |
1545 | sizeof(struct lpfc_name)); | 1551 | sizeof(struct lpfc_name)); |
1546 | if (!rc) | 1552 | if (!rc) { |
1553 | if (active_rrqs_xri_bitmap) | ||
1554 | mempool_free(active_rrqs_xri_bitmap, | ||
1555 | phba->active_rrq_pool); | ||
1547 | return ndlp; | 1556 | return ndlp; |
1557 | } | ||
1548 | new_ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_ATOMIC); | 1558 | new_ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_ATOMIC); |
1549 | if (!new_ndlp) | 1559 | if (!new_ndlp) { |
1560 | if (active_rrqs_xri_bitmap) | ||
1561 | mempool_free(active_rrqs_xri_bitmap, | ||
1562 | phba->active_rrq_pool); | ||
1550 | return ndlp; | 1563 | return ndlp; |
1564 | } | ||
1551 | lpfc_nlp_init(vport, new_ndlp, ndlp->nlp_DID); | 1565 | lpfc_nlp_init(vport, new_ndlp, ndlp->nlp_DID); |
1552 | } else if (!NLP_CHK_NODE_ACT(new_ndlp)) { | 1566 | } else if (!NLP_CHK_NODE_ACT(new_ndlp)) { |
1553 | rc = memcmp(&ndlp->nlp_portname, name, | 1567 | rc = memcmp(&ndlp->nlp_portname, name, |
1554 | sizeof(struct lpfc_name)); | 1568 | sizeof(struct lpfc_name)); |
1555 | if (!rc) | 1569 | if (!rc) { |
1570 | if (active_rrqs_xri_bitmap) | ||
1571 | mempool_free(active_rrqs_xri_bitmap, | ||
1572 | phba->active_rrq_pool); | ||
1556 | return ndlp; | 1573 | return ndlp; |
1574 | } | ||
1557 | new_ndlp = lpfc_enable_node(vport, new_ndlp, | 1575 | new_ndlp = lpfc_enable_node(vport, new_ndlp, |
1558 | NLP_STE_UNUSED_NODE); | 1576 | NLP_STE_UNUSED_NODE); |
1559 | if (!new_ndlp) | 1577 | if (!new_ndlp) { |
1578 | if (active_rrqs_xri_bitmap) | ||
1579 | mempool_free(active_rrqs_xri_bitmap, | ||
1580 | phba->active_rrq_pool); | ||
1560 | return ndlp; | 1581 | return ndlp; |
1582 | } | ||
1561 | keepDID = new_ndlp->nlp_DID; | 1583 | keepDID = new_ndlp->nlp_DID; |
1562 | if (phba->sli_rev == LPFC_SLI_REV4) | 1584 | if ((phba->sli_rev == LPFC_SLI_REV4) && active_rrqs_xri_bitmap) |
1563 | memcpy(&rrq.xri_bitmap, | 1585 | memcpy(active_rrqs_xri_bitmap, |
1564 | &new_ndlp->active_rrqs.xri_bitmap, | 1586 | new_ndlp->active_rrqs_xri_bitmap, |
1565 | sizeof(new_ndlp->active_rrqs.xri_bitmap)); | 1587 | phba->cfg_rrq_xri_bitmap_sz); |
1566 | } else { | 1588 | } else { |
1567 | keepDID = new_ndlp->nlp_DID; | 1589 | keepDID = new_ndlp->nlp_DID; |
1568 | if (phba->sli_rev == LPFC_SLI_REV4) | 1590 | if (phba->sli_rev == LPFC_SLI_REV4 && |
1569 | memcpy(&rrq.xri_bitmap, | 1591 | active_rrqs_xri_bitmap) |
1570 | &new_ndlp->active_rrqs.xri_bitmap, | 1592 | memcpy(active_rrqs_xri_bitmap, |
1571 | sizeof(new_ndlp->active_rrqs.xri_bitmap)); | 1593 | new_ndlp->active_rrqs_xri_bitmap, |
1594 | phba->cfg_rrq_xri_bitmap_sz); | ||
1572 | } | 1595 | } |
1573 | 1596 | ||
1574 | lpfc_unreg_rpi(vport, new_ndlp); | 1597 | lpfc_unreg_rpi(vport, new_ndlp); |
1575 | new_ndlp->nlp_DID = ndlp->nlp_DID; | 1598 | new_ndlp->nlp_DID = ndlp->nlp_DID; |
1576 | new_ndlp->nlp_prev_state = ndlp->nlp_prev_state; | 1599 | new_ndlp->nlp_prev_state = ndlp->nlp_prev_state; |
1577 | if (phba->sli_rev == LPFC_SLI_REV4) | 1600 | if (phba->sli_rev == LPFC_SLI_REV4) |
1578 | memcpy(new_ndlp->active_rrqs.xri_bitmap, | 1601 | memcpy(new_ndlp->active_rrqs_xri_bitmap, |
1579 | &ndlp->active_rrqs.xri_bitmap, | 1602 | ndlp->active_rrqs_xri_bitmap, |
1580 | sizeof(ndlp->active_rrqs.xri_bitmap)); | 1603 | phba->cfg_rrq_xri_bitmap_sz); |
1581 | 1604 | ||
1582 | if (ndlp->nlp_flag & NLP_NPR_2B_DISC) | 1605 | if (ndlp->nlp_flag & NLP_NPR_2B_DISC) |
1583 | new_ndlp->nlp_flag |= NLP_NPR_2B_DISC; | 1606 | new_ndlp->nlp_flag |= NLP_NPR_2B_DISC; |
@@ -1619,10 +1642,11 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, | |||
1619 | 1642 | ||
1620 | /* Two ndlps cannot have the same did on the nodelist */ | 1643 | /* Two ndlps cannot have the same did on the nodelist */ |
1621 | ndlp->nlp_DID = keepDID; | 1644 | ndlp->nlp_DID = keepDID; |
1622 | if (phba->sli_rev == LPFC_SLI_REV4) | 1645 | if (phba->sli_rev == LPFC_SLI_REV4 && |
1623 | memcpy(&ndlp->active_rrqs.xri_bitmap, | 1646 | active_rrqs_xri_bitmap) |
1624 | &rrq.xri_bitmap, | 1647 | memcpy(ndlp->active_rrqs_xri_bitmap, |
1625 | sizeof(ndlp->active_rrqs.xri_bitmap)); | 1648 | active_rrqs_xri_bitmap, |
1649 | phba->cfg_rrq_xri_bitmap_sz); | ||
1626 | lpfc_drop_node(vport, ndlp); | 1650 | lpfc_drop_node(vport, ndlp); |
1627 | } | 1651 | } |
1628 | else { | 1652 | else { |
@@ -1634,10 +1658,11 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, | |||
1634 | 1658 | ||
1635 | /* Two ndlps cannot have the same did */ | 1659 | /* Two ndlps cannot have the same did */ |
1636 | ndlp->nlp_DID = keepDID; | 1660 | ndlp->nlp_DID = keepDID; |
1637 | if (phba->sli_rev == LPFC_SLI_REV4) | 1661 | if (phba->sli_rev == LPFC_SLI_REV4 && |
1638 | memcpy(&ndlp->active_rrqs.xri_bitmap, | 1662 | active_rrqs_xri_bitmap) |
1639 | &rrq.xri_bitmap, | 1663 | memcpy(ndlp->active_rrqs_xri_bitmap, |
1640 | sizeof(ndlp->active_rrqs.xri_bitmap)); | 1664 | active_rrqs_xri_bitmap, |
1665 | phba->cfg_rrq_xri_bitmap_sz); | ||
1641 | 1666 | ||
1642 | /* Since we are swapping the ndlp passed in with the new one | 1667 | /* Since we are swapping the ndlp passed in with the new one |
1643 | * and the did has already been swapped, copy over state. | 1668 | * and the did has already been swapped, copy over state. |
@@ -1668,6 +1693,10 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, | |||
1668 | put_device(&rport->dev); | 1693 | put_device(&rport->dev); |
1669 | } | 1694 | } |
1670 | } | 1695 | } |
1696 | if (phba->sli_rev == LPFC_SLI_REV4 && | ||
1697 | active_rrqs_xri_bitmap) | ||
1698 | mempool_free(active_rrqs_xri_bitmap, | ||
1699 | phba->active_rrq_pool); | ||
1671 | return new_ndlp; | 1700 | return new_ndlp; |
1672 | } | 1701 | } |
1673 | 1702 | ||
@@ -2772,6 +2801,7 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) | |||
2772 | /* This will cause the callback-function lpfc_cmpl_els_cmd to | 2801 | /* This will cause the callback-function lpfc_cmpl_els_cmd to |
2773 | * trigger the release of node. | 2802 | * trigger the release of node. |
2774 | */ | 2803 | */ |
2804 | |||
2775 | lpfc_nlp_put(ndlp); | 2805 | lpfc_nlp_put(ndlp); |
2776 | return 0; | 2806 | return 0; |
2777 | } | 2807 | } |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index d6cc131a1221..6fee16030e40 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -4186,6 +4186,7 @@ lpfc_enable_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
4186 | struct lpfc_hba *phba = vport->phba; | 4186 | struct lpfc_hba *phba = vport->phba; |
4187 | uint32_t did; | 4187 | uint32_t did; |
4188 | unsigned long flags; | 4188 | unsigned long flags; |
4189 | unsigned long *active_rrqs_xri_bitmap = NULL; | ||
4189 | 4190 | ||
4190 | if (!ndlp) | 4191 | if (!ndlp) |
4191 | return NULL; | 4192 | return NULL; |
@@ -4214,12 +4215,17 @@ lpfc_enable_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
4214 | 4215 | ||
4215 | /* Keep the original DID */ | 4216 | /* Keep the original DID */ |
4216 | did = ndlp->nlp_DID; | 4217 | did = ndlp->nlp_DID; |
4218 | if (phba->sli_rev == LPFC_SLI_REV4) | ||
4219 | active_rrqs_xri_bitmap = ndlp->active_rrqs_xri_bitmap; | ||
4217 | 4220 | ||
4218 | /* re-initialize ndlp except of ndlp linked list pointer */ | 4221 | /* re-initialize ndlp except of ndlp linked list pointer */ |
4219 | memset((((char *)ndlp) + sizeof (struct list_head)), 0, | 4222 | memset((((char *)ndlp) + sizeof (struct list_head)), 0, |
4220 | sizeof (struct lpfc_nodelist) - sizeof (struct list_head)); | 4223 | sizeof (struct lpfc_nodelist) - sizeof (struct list_head)); |
4221 | lpfc_initialize_node(vport, ndlp, did); | 4224 | lpfc_initialize_node(vport, ndlp, did); |
4222 | 4225 | ||
4226 | if (phba->sli_rev == LPFC_SLI_REV4) | ||
4227 | ndlp->active_rrqs_xri_bitmap = active_rrqs_xri_bitmap; | ||
4228 | |||
4223 | spin_unlock_irqrestore(&phba->ndlp_lock, flags); | 4229 | spin_unlock_irqrestore(&phba->ndlp_lock, flags); |
4224 | if (vport->phba->sli_rev == LPFC_SLI_REV4) | 4230 | if (vport->phba->sli_rev == LPFC_SLI_REV4) |
4225 | ndlp->nlp_rpi = lpfc_sli4_alloc_rpi(vport->phba); | 4231 | ndlp->nlp_rpi = lpfc_sli4_alloc_rpi(vport->phba); |
@@ -4805,9 +4811,10 @@ __lpfc_findnode_did(struct lpfc_vport *vport, uint32_t did) | |||
4805 | ((uint32_t) ndlp->nlp_rpi & 0xff)); | 4811 | ((uint32_t) ndlp->nlp_rpi & 0xff)); |
4806 | lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, | 4812 | lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, |
4807 | "0929 FIND node DID " | 4813 | "0929 FIND node DID " |
4808 | "Data: x%p x%x x%x x%x\n", | 4814 | "Data: x%p x%x x%x x%x %p\n", |
4809 | ndlp, ndlp->nlp_DID, | 4815 | ndlp, ndlp->nlp_DID, |
4810 | ndlp->nlp_flag, data1); | 4816 | ndlp->nlp_flag, data1, |
4817 | ndlp->active_rrqs_xri_bitmap); | ||
4811 | return ndlp; | 4818 | return ndlp; |
4812 | } | 4819 | } |
4813 | } | 4820 | } |
@@ -5624,8 +5631,13 @@ lpfc_nlp_init(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
5624 | 5631 | ||
5625 | lpfc_initialize_node(vport, ndlp, did); | 5632 | lpfc_initialize_node(vport, ndlp, did); |
5626 | INIT_LIST_HEAD(&ndlp->nlp_listp); | 5633 | INIT_LIST_HEAD(&ndlp->nlp_listp); |
5627 | if (vport->phba->sli_rev == LPFC_SLI_REV4) | 5634 | if (vport->phba->sli_rev == LPFC_SLI_REV4) { |
5628 | ndlp->nlp_rpi = lpfc_sli4_alloc_rpi(vport->phba); | 5635 | ndlp->nlp_rpi = lpfc_sli4_alloc_rpi(vport->phba); |
5636 | ndlp->active_rrqs_xri_bitmap = | ||
5637 | mempool_alloc(vport->phba->active_rrq_pool, | ||
5638 | GFP_KERNEL); | ||
5639 | } | ||
5640 | |||
5629 | 5641 | ||
5630 | 5642 | ||
5631 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_NODE, | 5643 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_NODE, |
@@ -5670,6 +5682,9 @@ lpfc_nlp_release(struct kref *kref) | |||
5670 | /* free ndlp memory for final ndlp release */ | 5682 | /* free ndlp memory for final ndlp release */ |
5671 | if (NLP_CHK_FREE_REQ(ndlp)) { | 5683 | if (NLP_CHK_FREE_REQ(ndlp)) { |
5672 | kfree(ndlp->lat_data); | 5684 | kfree(ndlp->lat_data); |
5685 | if (phba->sli_rev == LPFC_SLI_REV4) | ||
5686 | mempool_free(ndlp->active_rrqs_xri_bitmap, | ||
5687 | ndlp->phba->active_rrq_pool); | ||
5673 | mempool_free(ndlp, ndlp->phba->nlp_mem_pool); | 5688 | mempool_free(ndlp, ndlp->phba->nlp_mem_pool); |
5674 | } | 5689 | } |
5675 | } | 5690 | } |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 68c94cc85c35..aa29ea099188 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -5061,6 +5061,9 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) | |||
5061 | rc = lpfc_sli4_read_config(phba); | 5061 | rc = lpfc_sli4_read_config(phba); |
5062 | if (unlikely(rc)) | 5062 | if (unlikely(rc)) |
5063 | goto out_free_bsmbx; | 5063 | goto out_free_bsmbx; |
5064 | rc = lpfc_mem_alloc_active_rrq_pool_s4(phba); | ||
5065 | if (unlikely(rc)) | ||
5066 | goto out_free_bsmbx; | ||
5064 | 5067 | ||
5065 | /* IF Type 0 ports get initialized now. */ | 5068 | /* IF Type 0 ports get initialized now. */ |
5066 | if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) == | 5069 | if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) == |
diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c index 812d0cd7c86d..b1db23c70781 100644 --- a/drivers/scsi/lpfc/lpfc_mem.c +++ b/drivers/scsi/lpfc/lpfc_mem.c | |||
@@ -38,10 +38,28 @@ | |||
38 | #include "lpfc_scsi.h" | 38 | #include "lpfc_scsi.h" |
39 | #include "lpfc.h" | 39 | #include "lpfc.h" |
40 | #include "lpfc_crtn.h" | 40 | #include "lpfc_crtn.h" |
41 | #include "lpfc_logmsg.h" | ||
41 | 42 | ||
42 | #define LPFC_MBUF_POOL_SIZE 64 /* max elements in MBUF safety pool */ | 43 | #define LPFC_MBUF_POOL_SIZE 64 /* max elements in MBUF safety pool */ |
43 | #define LPFC_MEM_POOL_SIZE 64 /* max elem in non-DMA safety pool */ | 44 | #define LPFC_MEM_POOL_SIZE 64 /* max elem in non-DMA safety pool */ |
44 | 45 | ||
46 | int | ||
47 | lpfc_mem_alloc_active_rrq_pool_s4(struct lpfc_hba *phba) { | ||
48 | size_t bytes; | ||
49 | int max_xri = phba->sli4_hba.max_cfg_param.max_xri; | ||
50 | |||
51 | if (max_xri <= 0) | ||
52 | return -ENOMEM; | ||
53 | bytes = ((BITS_PER_LONG - 1 + max_xri) / BITS_PER_LONG) * | ||
54 | sizeof(unsigned long); | ||
55 | phba->cfg_rrq_xri_bitmap_sz = bytes; | ||
56 | phba->active_rrq_pool = mempool_create_kmalloc_pool(LPFC_MEM_POOL_SIZE, | ||
57 | bytes); | ||
58 | if (!phba->active_rrq_pool) | ||
59 | return -ENOMEM; | ||
60 | else | ||
61 | return 0; | ||
62 | } | ||
45 | 63 | ||
46 | /** | 64 | /** |
47 | * lpfc_mem_alloc - create and allocate all PCI and memory pools | 65 | * lpfc_mem_alloc - create and allocate all PCI and memory pools |
@@ -209,6 +227,10 @@ lpfc_mem_free(struct lpfc_hba *phba) | |||
209 | /* Free NLP memory pool */ | 227 | /* Free NLP memory pool */ |
210 | mempool_destroy(phba->nlp_mem_pool); | 228 | mempool_destroy(phba->nlp_mem_pool); |
211 | phba->nlp_mem_pool = NULL; | 229 | phba->nlp_mem_pool = NULL; |
230 | if (phba->sli_rev == LPFC_SLI_REV4 && phba->active_rrq_pool) { | ||
231 | mempool_destroy(phba->active_rrq_pool); | ||
232 | phba->active_rrq_pool = NULL; | ||
233 | } | ||
212 | 234 | ||
213 | /* Free mbox memory pool */ | 235 | /* Free mbox memory pool */ |
214 | mempool_destroy(phba->mbox_mem_pool); | 236 | mempool_destroy(phba->mbox_mem_pool); |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 838e5b991851..c7181d85b993 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -635,7 +635,7 @@ lpfc_clr_rrq_active(struct lpfc_hba *phba, | |||
635 | if (!ndlp) | 635 | if (!ndlp) |
636 | goto out; | 636 | goto out; |
637 | 637 | ||
638 | if (test_and_clear_bit(xritag, ndlp->active_rrqs.xri_bitmap)) { | 638 | if (test_and_clear_bit(xritag, ndlp->active_rrqs_xri_bitmap)) { |
639 | rrq->send_rrq = 0; | 639 | rrq->send_rrq = 0; |
640 | rrq->xritag = 0; | 640 | rrq->xritag = 0; |
641 | rrq->rrq_stop_time = 0; | 641 | rrq->rrq_stop_time = 0; |
@@ -813,7 +813,9 @@ lpfc_test_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | |||
813 | { | 813 | { |
814 | if (!ndlp) | 814 | if (!ndlp) |
815 | return 0; | 815 | return 0; |
816 | if (test_bit(xritag, ndlp->active_rrqs.xri_bitmap)) | 816 | if (!ndlp->active_rrqs_xri_bitmap) |
817 | return 0; | ||
818 | if (test_bit(xritag, ndlp->active_rrqs_xri_bitmap)) | ||
817 | return 1; | 819 | return 1; |
818 | else | 820 | else |
819 | return 0; | 821 | return 0; |
@@ -863,7 +865,10 @@ lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | |||
863 | if (ndlp->vport && (ndlp->vport->load_flag & FC_UNLOADING)) | 865 | if (ndlp->vport && (ndlp->vport->load_flag & FC_UNLOADING)) |
864 | goto out; | 866 | goto out; |
865 | 867 | ||
866 | if (test_and_set_bit(xritag, ndlp->active_rrqs.xri_bitmap)) | 868 | if (!ndlp->active_rrqs_xri_bitmap) |
869 | goto out; | ||
870 | |||
871 | if (test_and_set_bit(xritag, ndlp->active_rrqs_xri_bitmap)) | ||
867 | goto out; | 872 | goto out; |
868 | 873 | ||
869 | spin_unlock_irqrestore(&phba->hbalock, iflags); | 874 | spin_unlock_irqrestore(&phba->hbalock, iflags); |