Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

James Smart and committed by
James Bottomley
cff261f6 0976e1a6

+110 -32
+2
drivers/scsi/lpfc/lpfc.h
··· 730 730 uint32_t cfg_request_firmware_upgrade; 731 731 uint32_t cfg_iocb_cnt; 732 732 uint32_t cfg_suppress_link_up; 733 + uint32_t cfg_rrq_xri_bitmap_sz; 733 734 #define LPFC_INITIALIZE_LINK 0 /* do normal init_link mbox */ 734 735 #define LPFC_DELAY_INIT_LINK 1 /* layered driver hold off */ 735 736 #define LPFC_DELAY_INIT_LINK_INDEFINITELY 2 /* wait, manual intervention */ ··· 836 835 mempool_t *mbox_mem_pool; 837 836 mempool_t *nlp_mem_pool; 838 837 mempool_t *rrq_pool; 838 + mempool_t *active_rrq_pool; 839 839 840 840 struct fc_host_statistics link_stats; 841 841 enum intr_type_t intr_type;
+1
drivers/scsi/lpfc/lpfc_crtn.h
··· 242 242 void lpfc_sli4_clear_fcf_rr_bmask(struct lpfc_hba *); 243 243 244 244 int lpfc_mem_alloc(struct lpfc_hba *, int align); 245 + int lpfc_mem_alloc_active_rrq_pool_s4(struct lpfc_hba *); 245 246 void lpfc_mem_free(struct lpfc_hba *); 246 247 void lpfc_mem_free_all(struct lpfc_hba *); 247 248 void lpfc_stop_vport_timers(struct lpfc_vport *);
+1 -1
drivers/scsi/lpfc/lpfc_disc.h
··· 116 116 atomic_t cmd_pending; 117 117 uint32_t cmd_qdepth; 118 118 unsigned long last_change_time; 119 - struct lpfc_node_rrqs active_rrqs; 119 + unsigned long *active_rrqs_xri_bitmap; 120 120 struct lpfc_scsicmd_bkt *lat_data; /* Latency data */ 121 121 }; 122 122 struct lpfc_node_rrq {
+55 -25
drivers/scsi/lpfc/lpfc_els.c
··· 1516 1516 uint32_t rc, keepDID = 0; 1517 1517 int put_node; 1518 1518 int put_rport; 1519 - struct lpfc_node_rrqs rrq; 1519 + unsigned long *active_rrqs_xri_bitmap = NULL; 1520 1520 1521 1521 /* Fabric nodes can have the same WWPN so we don't bother searching 1522 1522 * by WWPN. Just return the ndlp that was given to us. ··· 1534 1534 1535 1535 if (new_ndlp == ndlp && NLP_CHK_NODE_ACT(new_ndlp)) 1536 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 1545 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, 1540 1546 "3178 PLOGI confirm: ndlp %p x%x: new_ndlp %p\n", ··· 1549 1543 if (!new_ndlp) { 1550 1544 rc = memcmp(&ndlp->nlp_portname, name, 1551 1545 sizeof(struct lpfc_name)); 1552 - if (!rc) 1546 + if (!rc) { 1547 + if (active_rrqs_xri_bitmap) 1548 + mempool_free(active_rrqs_xri_bitmap, 1549 + phba->active_rrq_pool); 1553 1550 return ndlp; 1551 + } 1554 1552 new_ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_ATOMIC); 1555 - if (!new_ndlp) 1553 + if (!new_ndlp) { 1554 + if (active_rrqs_xri_bitmap) 1555 + mempool_free(active_rrqs_xri_bitmap, 1556 + phba->active_rrq_pool); 1556 1557 return ndlp; 1558 + } 1557 1559 lpfc_nlp_init(vport, new_ndlp, ndlp->nlp_DID); 1558 1560 } else if (!NLP_CHK_NODE_ACT(new_ndlp)) { 1559 1561 rc = memcmp(&ndlp->nlp_portname, name, 1560 1562 sizeof(struct lpfc_name)); 1561 - if (!rc) 1563 + if (!rc) { 1564 + if (active_rrqs_xri_bitmap) 1565 + mempool_free(active_rrqs_xri_bitmap, 1566 + phba->active_rrq_pool); 1562 1567 return ndlp; 1568 + } 1563 1569 new_ndlp = lpfc_enable_node(vport, new_ndlp, 1564 1570 NLP_STE_UNUSED_NODE); 1565 - if (!new_ndlp) 1571 + if (!new_ndlp) { 1572 + if (active_rrqs_xri_bitmap) 1573 + mempool_free(active_rrqs_xri_bitmap, 1574 + phba->active_rrq_pool); 1566 1575 return ndlp; 1576 + } 1567 1577 keepDID = new_ndlp->nlp_DID; 1568 - if (phba->sli_rev == LPFC_SLI_REV4) 1569 - memcpy(&rrq.xri_bitmap, 1570 - &new_ndlp->active_rrqs.xri_bitmap, 1571 - sizeof(new_ndlp->active_rrqs.xri_bitmap)); 1578 + if ((phba->sli_rev == LPFC_SLI_REV4) && active_rrqs_xri_bitmap) 1579 + memcpy(active_rrqs_xri_bitmap, 1580 + new_ndlp->active_rrqs_xri_bitmap, 1581 + phba->cfg_rrq_xri_bitmap_sz); 1572 1582 } else { 1573 1583 keepDID = new_ndlp->nlp_DID; 1574 - if (phba->sli_rev == LPFC_SLI_REV4) 1575 - memcpy(&rrq.xri_bitmap, 1576 - &new_ndlp->active_rrqs.xri_bitmap, 1577 - sizeof(new_ndlp->active_rrqs.xri_bitmap)); 1584 + if (phba->sli_rev == LPFC_SLI_REV4 && 1585 + active_rrqs_xri_bitmap) 1586 + memcpy(active_rrqs_xri_bitmap, 1587 + new_ndlp->active_rrqs_xri_bitmap, 1588 + phba->cfg_rrq_xri_bitmap_sz); 1578 1589 } 1579 1590 1580 1591 lpfc_unreg_rpi(vport, new_ndlp); 1581 1592 new_ndlp->nlp_DID = ndlp->nlp_DID; 1582 1593 new_ndlp->nlp_prev_state = ndlp->nlp_prev_state; 1583 1594 if (phba->sli_rev == LPFC_SLI_REV4) 1584 - memcpy(new_ndlp->active_rrqs.xri_bitmap, 1585 - &ndlp->active_rrqs.xri_bitmap, 1586 - sizeof(ndlp->active_rrqs.xri_bitmap)); 1595 + memcpy(new_ndlp->active_rrqs_xri_bitmap, 1596 + ndlp->active_rrqs_xri_bitmap, 1597 + phba->cfg_rrq_xri_bitmap_sz); 1587 1598 1588 1599 if (ndlp->nlp_flag & NLP_NPR_2B_DISC) 1589 1600 new_ndlp->nlp_flag |= NLP_NPR_2B_DISC; ··· 1642 1619 1643 1620 /* Two ndlps cannot have the same did on the nodelist */ 1644 1621 ndlp->nlp_DID = keepDID; 1645 - if (phba->sli_rev == LPFC_SLI_REV4) 1646 - memcpy(&ndlp->active_rrqs.xri_bitmap, 1647 - &rrq.xri_bitmap, 1648 - sizeof(ndlp->active_rrqs.xri_bitmap)); 1622 + if (phba->sli_rev == LPFC_SLI_REV4 && 1623 + active_rrqs_xri_bitmap) 1624 + memcpy(ndlp->active_rrqs_xri_bitmap, 1625 + active_rrqs_xri_bitmap, 1626 + phba->cfg_rrq_xri_bitmap_sz); 1649 1627 lpfc_drop_node(vport, ndlp); 1650 1628 } 1651 1629 else { ··· 1658 1634 1659 1635 /* Two ndlps cannot have the same did */ 1660 1636 ndlp->nlp_DID = keepDID; 1661 - if (phba->sli_rev == LPFC_SLI_REV4) 1662 - memcpy(&ndlp->active_rrqs.xri_bitmap, 1663 - &rrq.xri_bitmap, 1664 - sizeof(ndlp->active_rrqs.xri_bitmap)); 1637 + if (phba->sli_rev == LPFC_SLI_REV4 && 1638 + active_rrqs_xri_bitmap) 1639 + memcpy(ndlp->active_rrqs_xri_bitmap, 1640 + active_rrqs_xri_bitmap, 1641 + phba->cfg_rrq_xri_bitmap_sz); 1665 1642 1666 1643 /* Since we are swapping the ndlp passed in with the new one 1667 1644 * and the did has already been swapped, copy over state. ··· 1693 1668 put_device(&rport->dev); 1694 1669 } 1695 1670 } 1671 + if (phba->sli_rev == LPFC_SLI_REV4 && 1672 + active_rrqs_xri_bitmap) 1673 + mempool_free(active_rrqs_xri_bitmap, 1674 + phba->active_rrq_pool); 1696 1675 return new_ndlp; 1697 1676 } 1698 1677 ··· 2801 2772 /* This will cause the callback-function lpfc_cmpl_els_cmd to 2802 2773 * trigger the release of node. 2803 2774 */ 2775 + 2804 2776 lpfc_nlp_put(ndlp); 2805 2777 return 0; 2806 2778 }
+18 -3
drivers/scsi/lpfc/lpfc_hbadisc.c
··· 4186 4186 struct lpfc_hba *phba = vport->phba; 4187 4187 uint32_t did; 4188 4188 unsigned long flags; 4189 + unsigned long *active_rrqs_xri_bitmap = NULL; 4189 4190 4190 4191 if (!ndlp) 4191 4192 return NULL; ··· 4215 4214 4216 4215 /* Keep the original DID */ 4217 4216 did = ndlp->nlp_DID; 4217 + if (phba->sli_rev == LPFC_SLI_REV4) 4218 + active_rrqs_xri_bitmap = ndlp->active_rrqs_xri_bitmap; 4218 4219 4219 4220 /* re-initialize ndlp except of ndlp linked list pointer */ 4220 4221 memset((((char *)ndlp) + sizeof (struct list_head)), 0, 4221 4222 sizeof (struct lpfc_nodelist) - sizeof (struct list_head)); 4222 4223 lpfc_initialize_node(vport, ndlp, did); 4224 + 4225 + if (phba->sli_rev == LPFC_SLI_REV4) 4226 + ndlp->active_rrqs_xri_bitmap = active_rrqs_xri_bitmap; 4223 4227 4224 4228 spin_unlock_irqrestore(&phba->ndlp_lock, flags); 4225 4229 if (vport->phba->sli_rev == LPFC_SLI_REV4) ··· 4811 4805 ((uint32_t) ndlp->nlp_rpi & 0xff)); 4812 4806 lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, 4813 4807 "0929 FIND node DID " 4814 - "Data: x%p x%x x%x x%x\n", 4808 + "Data: x%p x%x x%x x%x %p\n", 4815 4809 ndlp, ndlp->nlp_DID, 4816 - ndlp->nlp_flag, data1); 4810 + ndlp->nlp_flag, data1, 4811 + ndlp->active_rrqs_xri_bitmap); 4817 4812 return ndlp; 4818 4813 } 4819 4814 } ··· 5631 5624 5632 5625 lpfc_initialize_node(vport, ndlp, did); 5633 5626 INIT_LIST_HEAD(&ndlp->nlp_listp); 5634 - if (vport->phba->sli_rev == LPFC_SLI_REV4) 5627 + if (vport->phba->sli_rev == LPFC_SLI_REV4) { 5635 5628 ndlp->nlp_rpi = lpfc_sli4_alloc_rpi(vport->phba); 5629 + ndlp->active_rrqs_xri_bitmap = 5630 + mempool_alloc(vport->phba->active_rrq_pool, 5631 + GFP_KERNEL); 5632 + } 5633 + 5636 5634 5637 5635 5638 5636 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_NODE, ··· 5682 5670 /* free ndlp memory for final ndlp release */ 5683 5671 if (NLP_CHK_FREE_REQ(ndlp)) { 5684 5672 kfree(ndlp->lat_data); 5673 + if (phba->sli_rev == LPFC_SLI_REV4) 5674 + mempool_free(ndlp->active_rrqs_xri_bitmap, 5675 + ndlp->phba->active_rrq_pool); 5685 5676 mempool_free(ndlp, ndlp->phba->nlp_mem_pool); 5686 5677 } 5687 5678 }
+3
drivers/scsi/lpfc/lpfc_init.c
··· 5061 5061 rc = lpfc_sli4_read_config(phba); 5062 5062 if (unlikely(rc)) 5063 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 5068 /* IF Type 0 ports get initialized now. */ 5066 5069 if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) ==
+22
drivers/scsi/lpfc/lpfc_mem.c
··· 38 38 #include "lpfc_scsi.h" 39 39 #include "lpfc.h" 40 40 #include "lpfc_crtn.h" 41 + #include "lpfc_logmsg.h" 41 42 42 43 #define LPFC_MBUF_POOL_SIZE 64 /* max elements in MBUF safety pool */ 43 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 65 * lpfc_mem_alloc - create and allocate all PCI and memory pools ··· 227 209 /* Free NLP memory pool */ 228 210 mempool_destroy(phba->nlp_mem_pool); 229 211 phba->nlp_mem_pool = NULL; 212 + if (phba->sli_rev == LPFC_SLI_REV4 && phba->active_rrq_pool) { 213 + mempool_destroy(phba->active_rrq_pool); 214 + phba->active_rrq_pool = NULL; 215 + } 230 216 231 217 /* Free mbox memory pool */ 232 218 mempool_destroy(phba->mbox_mem_pool);
+8 -3
drivers/scsi/lpfc/lpfc_sli.c
··· 635 635 if (!ndlp) 636 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 639 rrq->send_rrq = 0; 640 640 rrq->xritag = 0; 641 641 rrq->rrq_stop_time = 0; ··· 813 813 { 814 814 if (!ndlp) 815 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 819 return 1; 818 820 else 819 821 return 0; ··· 865 863 if (ndlp->vport && (ndlp->vport->load_flag & FC_UNLOADING)) 866 864 goto out; 867 865 868 - if (test_and_set_bit(xritag, ndlp->active_rrqs.xri_bitmap)) 866 + if (!ndlp->active_rrqs_xri_bitmap) 867 + goto out; 868 + 869 + if (test_and_set_bit(xritag, ndlp->active_rrqs_xri_bitmap)) 869 870 goto out; 870 871 871 872 spin_unlock_irqrestore(&phba->hbalock, iflags);