diff options
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 15 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_attr.c | 123 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 9 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_ct.c | 49 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_debugfs.c | 962 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_debugfs.h | 60 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 173 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 18 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hw.h | 11 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hw4.h | 104 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 134 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_mbox.c | 19 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nportdisc.c | 11 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 113 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 217 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli4.h | 8 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_version.h | 4 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_vport.c | 4 |
18 files changed, 1738 insertions, 296 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 746dd3d7a092..b64c6da870d3 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2004-2010 Emulex. All rights reserved. * | 4 | * Copyright (C) 2004-2011 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * | 7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * |
@@ -325,6 +325,7 @@ struct lpfc_vport { | |||
325 | #define FC_VPORT_CVL_RCVD 0x400000 /* VLink failed due to CVL */ | 325 | #define FC_VPORT_CVL_RCVD 0x400000 /* VLink failed due to CVL */ |
326 | #define FC_VFI_REGISTERED 0x800000 /* VFI is registered */ | 326 | #define FC_VFI_REGISTERED 0x800000 /* VFI is registered */ |
327 | #define FC_FDISC_COMPLETED 0x1000000/* FDISC completed */ | 327 | #define FC_FDISC_COMPLETED 0x1000000/* FDISC completed */ |
328 | #define FC_DISC_DELAYED 0x2000000/* Delay NPort discovery */ | ||
328 | 329 | ||
329 | uint32_t ct_flags; | 330 | uint32_t ct_flags; |
330 | #define FC_CT_RFF_ID 0x1 /* RFF_ID accepted by switch */ | 331 | #define FC_CT_RFF_ID 0x1 /* RFF_ID accepted by switch */ |
@@ -348,6 +349,8 @@ struct lpfc_vport { | |||
348 | 349 | ||
349 | uint32_t fc_myDID; /* fibre channel S_ID */ | 350 | uint32_t fc_myDID; /* fibre channel S_ID */ |
350 | uint32_t fc_prevDID; /* previous fibre channel S_ID */ | 351 | uint32_t fc_prevDID; /* previous fibre channel S_ID */ |
352 | struct lpfc_name fabric_portname; | ||
353 | struct lpfc_name fabric_nodename; | ||
351 | 354 | ||
352 | int32_t stopped; /* HBA has not been restarted since last ERATT */ | 355 | int32_t stopped; /* HBA has not been restarted since last ERATT */ |
353 | uint8_t fc_linkspeed; /* Link speed after last READ_LA */ | 356 | uint8_t fc_linkspeed; /* Link speed after last READ_LA */ |
@@ -372,6 +375,7 @@ struct lpfc_vport { | |||
372 | #define WORKER_DISC_TMO 0x1 /* vport: Discovery timeout */ | 375 | #define WORKER_DISC_TMO 0x1 /* vport: Discovery timeout */ |
373 | #define WORKER_ELS_TMO 0x2 /* vport: ELS timeout */ | 376 | #define WORKER_ELS_TMO 0x2 /* vport: ELS timeout */ |
374 | #define WORKER_FDMI_TMO 0x4 /* vport: FDMI timeout */ | 377 | #define WORKER_FDMI_TMO 0x4 /* vport: FDMI timeout */ |
378 | #define WORKER_DELAYED_DISC_TMO 0x8 /* vport: delayed discovery */ | ||
375 | 379 | ||
376 | #define WORKER_MBOX_TMO 0x100 /* hba: MBOX timeout */ | 380 | #define WORKER_MBOX_TMO 0x100 /* hba: MBOX timeout */ |
377 | #define WORKER_HB_TMO 0x200 /* hba: Heart beat timeout */ | 381 | #define WORKER_HB_TMO 0x200 /* hba: Heart beat timeout */ |
@@ -382,6 +386,7 @@ struct lpfc_vport { | |||
382 | 386 | ||
383 | struct timer_list fc_fdmitmo; | 387 | struct timer_list fc_fdmitmo; |
384 | struct timer_list els_tmofunc; | 388 | struct timer_list els_tmofunc; |
389 | struct timer_list delayed_disc_tmo; | ||
385 | 390 | ||
386 | int unreg_vpi_cmpl; | 391 | int unreg_vpi_cmpl; |
387 | 392 | ||
@@ -548,6 +553,8 @@ struct lpfc_hba { | |||
548 | #define LPFC_SLI3_CRP_ENABLED 0x08 | 553 | #define LPFC_SLI3_CRP_ENABLED 0x08 |
549 | #define LPFC_SLI3_BG_ENABLED 0x20 | 554 | #define LPFC_SLI3_BG_ENABLED 0x20 |
550 | #define LPFC_SLI3_DSS_ENABLED 0x40 | 555 | #define LPFC_SLI3_DSS_ENABLED 0x40 |
556 | #define LPFC_SLI4_PERFH_ENABLED 0x80 | ||
557 | #define LPFC_SLI4_PHWQ_ENABLED 0x100 | ||
551 | uint32_t iocb_cmd_size; | 558 | uint32_t iocb_cmd_size; |
552 | uint32_t iocb_rsp_size; | 559 | uint32_t iocb_rsp_size; |
553 | 560 | ||
@@ -655,7 +662,7 @@ struct lpfc_hba { | |||
655 | #define LPFC_INITIALIZE_LINK 0 /* do normal init_link mbox */ | 662 | #define LPFC_INITIALIZE_LINK 0 /* do normal init_link mbox */ |
656 | #define LPFC_DELAY_INIT_LINK 1 /* layered driver hold off */ | 663 | #define LPFC_DELAY_INIT_LINK 1 /* layered driver hold off */ |
657 | #define LPFC_DELAY_INIT_LINK_INDEFINITELY 2 /* wait, manual intervention */ | 664 | #define LPFC_DELAY_INIT_LINK_INDEFINITELY 2 /* wait, manual intervention */ |
658 | 665 | uint32_t cfg_enable_dss; | |
659 | lpfc_vpd_t vpd; /* vital product data */ | 666 | lpfc_vpd_t vpd; /* vital product data */ |
660 | 667 | ||
661 | struct pci_dev *pcidev; | 668 | struct pci_dev *pcidev; |
@@ -792,6 +799,10 @@ struct lpfc_hba { | |||
792 | struct dentry *debug_slow_ring_trc; | 799 | struct dentry *debug_slow_ring_trc; |
793 | struct lpfc_debugfs_trc *slow_ring_trc; | 800 | struct lpfc_debugfs_trc *slow_ring_trc; |
794 | atomic_t slow_ring_trc_cnt; | 801 | atomic_t slow_ring_trc_cnt; |
802 | /* iDiag debugfs sub-directory */ | ||
803 | struct dentry *idiag_root; | ||
804 | struct dentry *idiag_pci_cfg; | ||
805 | struct dentry *idiag_que_info; | ||
795 | #endif | 806 | #endif |
796 | 807 | ||
797 | /* Used for deferred freeing of ELS data buffers */ | 808 | /* Used for deferred freeing of ELS data buffers */ |
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 3512abb8a587..e7c020df12fa 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2004-2009 Emulex. All rights reserved. * | 4 | * Copyright (C) 2004-2011 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * | 7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * |
@@ -623,10 +623,14 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type) | |||
623 | int status = 0; | 623 | int status = 0; |
624 | int cnt = 0; | 624 | int cnt = 0; |
625 | int i; | 625 | int i; |
626 | int rc; | ||
626 | 627 | ||
627 | init_completion(&online_compl); | 628 | init_completion(&online_compl); |
628 | lpfc_workq_post_event(phba, &status, &online_compl, | 629 | rc = lpfc_workq_post_event(phba, &status, &online_compl, |
629 | LPFC_EVT_OFFLINE_PREP); | 630 | LPFC_EVT_OFFLINE_PREP); |
631 | if (rc == 0) | ||
632 | return -ENOMEM; | ||
633 | |||
630 | wait_for_completion(&online_compl); | 634 | wait_for_completion(&online_compl); |
631 | 635 | ||
632 | if (status != 0) | 636 | if (status != 0) |
@@ -652,7 +656,10 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type) | |||
652 | } | 656 | } |
653 | 657 | ||
654 | init_completion(&online_compl); | 658 | init_completion(&online_compl); |
655 | lpfc_workq_post_event(phba, &status, &online_compl, type); | 659 | rc = lpfc_workq_post_event(phba, &status, &online_compl, type); |
660 | if (rc == 0) | ||
661 | return -ENOMEM; | ||
662 | |||
656 | wait_for_completion(&online_compl); | 663 | wait_for_completion(&online_compl); |
657 | 664 | ||
658 | if (status != 0) | 665 | if (status != 0) |
@@ -671,6 +678,7 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type) | |||
671 | * | 678 | * |
672 | * Notes: | 679 | * Notes: |
673 | * Assumes any error from lpfc_do_offline() will be negative. | 680 | * Assumes any error from lpfc_do_offline() will be negative. |
681 | * Do not make this function static. | ||
674 | * | 682 | * |
675 | * Returns: | 683 | * Returns: |
676 | * lpfc_do_offline() return code if not zero | 684 | * lpfc_do_offline() return code if not zero |
@@ -682,6 +690,7 @@ lpfc_selective_reset(struct lpfc_hba *phba) | |||
682 | { | 690 | { |
683 | struct completion online_compl; | 691 | struct completion online_compl; |
684 | int status = 0; | 692 | int status = 0; |
693 | int rc; | ||
685 | 694 | ||
686 | if (!phba->cfg_enable_hba_reset) | 695 | if (!phba->cfg_enable_hba_reset) |
687 | return -EIO; | 696 | return -EIO; |
@@ -692,8 +701,11 @@ lpfc_selective_reset(struct lpfc_hba *phba) | |||
692 | return status; | 701 | return status; |
693 | 702 | ||
694 | init_completion(&online_compl); | 703 | init_completion(&online_compl); |
695 | lpfc_workq_post_event(phba, &status, &online_compl, | 704 | rc = lpfc_workq_post_event(phba, &status, &online_compl, |
696 | LPFC_EVT_ONLINE); | 705 | LPFC_EVT_ONLINE); |
706 | if (rc == 0) | ||
707 | return -ENOMEM; | ||
708 | |||
697 | wait_for_completion(&online_compl); | 709 | wait_for_completion(&online_compl); |
698 | 710 | ||
699 | if (status != 0) | 711 | if (status != 0) |
@@ -812,14 +824,17 @@ lpfc_board_mode_store(struct device *dev, struct device_attribute *attr, | |||
812 | struct lpfc_hba *phba = vport->phba; | 824 | struct lpfc_hba *phba = vport->phba; |
813 | struct completion online_compl; | 825 | struct completion online_compl; |
814 | int status=0; | 826 | int status=0; |
827 | int rc; | ||
815 | 828 | ||
816 | if (!phba->cfg_enable_hba_reset) | 829 | if (!phba->cfg_enable_hba_reset) |
817 | return -EACCES; | 830 | return -EACCES; |
818 | init_completion(&online_compl); | 831 | init_completion(&online_compl); |
819 | 832 | ||
820 | if(strncmp(buf, "online", sizeof("online") - 1) == 0) { | 833 | if(strncmp(buf, "online", sizeof("online") - 1) == 0) { |
821 | lpfc_workq_post_event(phba, &status, &online_compl, | 834 | rc = lpfc_workq_post_event(phba, &status, &online_compl, |
822 | LPFC_EVT_ONLINE); | 835 | LPFC_EVT_ONLINE); |
836 | if (rc == 0) | ||
837 | return -ENOMEM; | ||
823 | wait_for_completion(&online_compl); | 838 | wait_for_completion(&online_compl); |
824 | } else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0) | 839 | } else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0) |
825 | status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); | 840 | status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); |
@@ -1279,6 +1294,28 @@ lpfc_fips_rev_show(struct device *dev, struct device_attribute *attr, | |||
1279 | } | 1294 | } |
1280 | 1295 | ||
1281 | /** | 1296 | /** |
1297 | * lpfc_dss_show - Return the current state of dss and the configured state | ||
1298 | * @dev: class converted to a Scsi_host structure. | ||
1299 | * @attr: device attribute, not used. | ||
1300 | * @buf: on return contains the formatted text. | ||
1301 | * | ||
1302 | * Returns: size of formatted string. | ||
1303 | **/ | ||
1304 | static ssize_t | ||
1305 | lpfc_dss_show(struct device *dev, struct device_attribute *attr, | ||
1306 | char *buf) | ||
1307 | { | ||
1308 | struct Scsi_Host *shost = class_to_shost(dev); | ||
1309 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; | ||
1310 | struct lpfc_hba *phba = vport->phba; | ||
1311 | |||
1312 | return snprintf(buf, PAGE_SIZE, "%s - %sOperational\n", | ||
1313 | (phba->cfg_enable_dss) ? "Enabled" : "Disabled", | ||
1314 | (phba->sli3_options & LPFC_SLI3_DSS_ENABLED) ? | ||
1315 | "" : "Not "); | ||
1316 | } | ||
1317 | |||
1318 | /** | ||
1282 | * lpfc_param_show - Return a cfg attribute value in decimal | 1319 | * lpfc_param_show - Return a cfg attribute value in decimal |
1283 | * | 1320 | * |
1284 | * Description: | 1321 | * Description: |
@@ -1597,13 +1634,13 @@ lpfc_##attr##_store(struct device *dev, struct device_attribute *attr, \ | |||
1597 | 1634 | ||
1598 | #define LPFC_ATTR(name, defval, minval, maxval, desc) \ | 1635 | #define LPFC_ATTR(name, defval, minval, maxval, desc) \ |
1599 | static uint lpfc_##name = defval;\ | 1636 | static uint lpfc_##name = defval;\ |
1600 | module_param(lpfc_##name, uint, 0);\ | 1637 | module_param(lpfc_##name, uint, S_IRUGO);\ |
1601 | MODULE_PARM_DESC(lpfc_##name, desc);\ | 1638 | MODULE_PARM_DESC(lpfc_##name, desc);\ |
1602 | lpfc_param_init(name, defval, minval, maxval) | 1639 | lpfc_param_init(name, defval, minval, maxval) |
1603 | 1640 | ||
1604 | #define LPFC_ATTR_R(name, defval, minval, maxval, desc) \ | 1641 | #define LPFC_ATTR_R(name, defval, minval, maxval, desc) \ |
1605 | static uint lpfc_##name = defval;\ | 1642 | static uint lpfc_##name = defval;\ |
1606 | module_param(lpfc_##name, uint, 0);\ | 1643 | module_param(lpfc_##name, uint, S_IRUGO);\ |
1607 | MODULE_PARM_DESC(lpfc_##name, desc);\ | 1644 | MODULE_PARM_DESC(lpfc_##name, desc);\ |
1608 | lpfc_param_show(name)\ | 1645 | lpfc_param_show(name)\ |
1609 | lpfc_param_init(name, defval, minval, maxval)\ | 1646 | lpfc_param_init(name, defval, minval, maxval)\ |
@@ -1611,7 +1648,7 @@ static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL) | |||
1611 | 1648 | ||
1612 | #define LPFC_ATTR_RW(name, defval, minval, maxval, desc) \ | 1649 | #define LPFC_ATTR_RW(name, defval, minval, maxval, desc) \ |
1613 | static uint lpfc_##name = defval;\ | 1650 | static uint lpfc_##name = defval;\ |
1614 | module_param(lpfc_##name, uint, 0);\ | 1651 | module_param(lpfc_##name, uint, S_IRUGO);\ |
1615 | MODULE_PARM_DESC(lpfc_##name, desc);\ | 1652 | MODULE_PARM_DESC(lpfc_##name, desc);\ |
1616 | lpfc_param_show(name)\ | 1653 | lpfc_param_show(name)\ |
1617 | lpfc_param_init(name, defval, minval, maxval)\ | 1654 | lpfc_param_init(name, defval, minval, maxval)\ |
@@ -1622,7 +1659,7 @@ static DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\ | |||
1622 | 1659 | ||
1623 | #define LPFC_ATTR_HEX_R(name, defval, minval, maxval, desc) \ | 1660 | #define LPFC_ATTR_HEX_R(name, defval, minval, maxval, desc) \ |
1624 | static uint lpfc_##name = defval;\ | 1661 | static uint lpfc_##name = defval;\ |
1625 | module_param(lpfc_##name, uint, 0);\ | 1662 | module_param(lpfc_##name, uint, S_IRUGO);\ |
1626 | MODULE_PARM_DESC(lpfc_##name, desc);\ | 1663 | MODULE_PARM_DESC(lpfc_##name, desc);\ |
1627 | lpfc_param_hex_show(name)\ | 1664 | lpfc_param_hex_show(name)\ |
1628 | lpfc_param_init(name, defval, minval, maxval)\ | 1665 | lpfc_param_init(name, defval, minval, maxval)\ |
@@ -1630,7 +1667,7 @@ static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL) | |||
1630 | 1667 | ||
1631 | #define LPFC_ATTR_HEX_RW(name, defval, minval, maxval, desc) \ | 1668 | #define LPFC_ATTR_HEX_RW(name, defval, minval, maxval, desc) \ |
1632 | static uint lpfc_##name = defval;\ | 1669 | static uint lpfc_##name = defval;\ |
1633 | module_param(lpfc_##name, uint, 0);\ | 1670 | module_param(lpfc_##name, uint, S_IRUGO);\ |
1634 | MODULE_PARM_DESC(lpfc_##name, desc);\ | 1671 | MODULE_PARM_DESC(lpfc_##name, desc);\ |
1635 | lpfc_param_hex_show(name)\ | 1672 | lpfc_param_hex_show(name)\ |
1636 | lpfc_param_init(name, defval, minval, maxval)\ | 1673 | lpfc_param_init(name, defval, minval, maxval)\ |
@@ -1641,13 +1678,13 @@ static DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\ | |||
1641 | 1678 | ||
1642 | #define LPFC_VPORT_ATTR(name, defval, minval, maxval, desc) \ | 1679 | #define LPFC_VPORT_ATTR(name, defval, minval, maxval, desc) \ |
1643 | static uint lpfc_##name = defval;\ | 1680 | static uint lpfc_##name = defval;\ |
1644 | module_param(lpfc_##name, uint, 0);\ | 1681 | module_param(lpfc_##name, uint, S_IRUGO);\ |
1645 | MODULE_PARM_DESC(lpfc_##name, desc);\ | 1682 | MODULE_PARM_DESC(lpfc_##name, desc);\ |
1646 | lpfc_vport_param_init(name, defval, minval, maxval) | 1683 | lpfc_vport_param_init(name, defval, minval, maxval) |
1647 | 1684 | ||
1648 | #define LPFC_VPORT_ATTR_R(name, defval, minval, maxval, desc) \ | 1685 | #define LPFC_VPORT_ATTR_R(name, defval, minval, maxval, desc) \ |
1649 | static uint lpfc_##name = defval;\ | 1686 | static uint lpfc_##name = defval;\ |
1650 | module_param(lpfc_##name, uint, 0);\ | 1687 | module_param(lpfc_##name, uint, S_IRUGO);\ |
1651 | MODULE_PARM_DESC(lpfc_##name, desc);\ | 1688 | MODULE_PARM_DESC(lpfc_##name, desc);\ |
1652 | lpfc_vport_param_show(name)\ | 1689 | lpfc_vport_param_show(name)\ |
1653 | lpfc_vport_param_init(name, defval, minval, maxval)\ | 1690 | lpfc_vport_param_init(name, defval, minval, maxval)\ |
@@ -1655,7 +1692,7 @@ static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL) | |||
1655 | 1692 | ||
1656 | #define LPFC_VPORT_ATTR_RW(name, defval, minval, maxval, desc) \ | 1693 | #define LPFC_VPORT_ATTR_RW(name, defval, minval, maxval, desc) \ |
1657 | static uint lpfc_##name = defval;\ | 1694 | static uint lpfc_##name = defval;\ |
1658 | module_param(lpfc_##name, uint, 0);\ | 1695 | module_param(lpfc_##name, uint, S_IRUGO);\ |
1659 | MODULE_PARM_DESC(lpfc_##name, desc);\ | 1696 | MODULE_PARM_DESC(lpfc_##name, desc);\ |
1660 | lpfc_vport_param_show(name)\ | 1697 | lpfc_vport_param_show(name)\ |
1661 | lpfc_vport_param_init(name, defval, minval, maxval)\ | 1698 | lpfc_vport_param_init(name, defval, minval, maxval)\ |
@@ -1666,7 +1703,7 @@ static DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\ | |||
1666 | 1703 | ||
1667 | #define LPFC_VPORT_ATTR_HEX_R(name, defval, minval, maxval, desc) \ | 1704 | #define LPFC_VPORT_ATTR_HEX_R(name, defval, minval, maxval, desc) \ |
1668 | static uint lpfc_##name = defval;\ | 1705 | static uint lpfc_##name = defval;\ |
1669 | module_param(lpfc_##name, uint, 0);\ | 1706 | module_param(lpfc_##name, uint, S_IRUGO);\ |
1670 | MODULE_PARM_DESC(lpfc_##name, desc);\ | 1707 | MODULE_PARM_DESC(lpfc_##name, desc);\ |
1671 | lpfc_vport_param_hex_show(name)\ | 1708 | lpfc_vport_param_hex_show(name)\ |
1672 | lpfc_vport_param_init(name, defval, minval, maxval)\ | 1709 | lpfc_vport_param_init(name, defval, minval, maxval)\ |
@@ -1674,7 +1711,7 @@ static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL) | |||
1674 | 1711 | ||
1675 | #define LPFC_VPORT_ATTR_HEX_RW(name, defval, minval, maxval, desc) \ | 1712 | #define LPFC_VPORT_ATTR_HEX_RW(name, defval, minval, maxval, desc) \ |
1676 | static uint lpfc_##name = defval;\ | 1713 | static uint lpfc_##name = defval;\ |
1677 | module_param(lpfc_##name, uint, 0);\ | 1714 | module_param(lpfc_##name, uint, S_IRUGO);\ |
1678 | MODULE_PARM_DESC(lpfc_##name, desc);\ | 1715 | MODULE_PARM_DESC(lpfc_##name, desc);\ |
1679 | lpfc_vport_param_hex_show(name)\ | 1716 | lpfc_vport_param_hex_show(name)\ |
1680 | lpfc_vport_param_init(name, defval, minval, maxval)\ | 1717 | lpfc_vport_param_init(name, defval, minval, maxval)\ |
@@ -1718,7 +1755,7 @@ static DEVICE_ATTR(npiv_info, S_IRUGO, lpfc_npiv_info_show, NULL); | |||
1718 | static DEVICE_ATTR(lpfc_temp_sensor, S_IRUGO, lpfc_temp_sensor_show, NULL); | 1755 | static DEVICE_ATTR(lpfc_temp_sensor, S_IRUGO, lpfc_temp_sensor_show, NULL); |
1719 | static DEVICE_ATTR(lpfc_fips_level, S_IRUGO, lpfc_fips_level_show, NULL); | 1756 | static DEVICE_ATTR(lpfc_fips_level, S_IRUGO, lpfc_fips_level_show, NULL); |
1720 | static DEVICE_ATTR(lpfc_fips_rev, S_IRUGO, lpfc_fips_rev_show, NULL); | 1757 | static DEVICE_ATTR(lpfc_fips_rev, S_IRUGO, lpfc_fips_rev_show, NULL); |
1721 | 1758 | static DEVICE_ATTR(lpfc_dss, S_IRUGO, lpfc_dss_show, NULL); | |
1722 | 1759 | ||
1723 | static char *lpfc_soft_wwn_key = "C99G71SL8032A"; | 1760 | static char *lpfc_soft_wwn_key = "C99G71SL8032A"; |
1724 | 1761 | ||
@@ -1813,6 +1850,7 @@ lpfc_soft_wwpn_store(struct device *dev, struct device_attribute *attr, | |||
1813 | int stat1=0, stat2=0; | 1850 | int stat1=0, stat2=0; |
1814 | unsigned int i, j, cnt=count; | 1851 | unsigned int i, j, cnt=count; |
1815 | u8 wwpn[8]; | 1852 | u8 wwpn[8]; |
1853 | int rc; | ||
1816 | 1854 | ||
1817 | if (!phba->cfg_enable_hba_reset) | 1855 | if (!phba->cfg_enable_hba_reset) |
1818 | return -EACCES; | 1856 | return -EACCES; |
@@ -1863,7 +1901,11 @@ lpfc_soft_wwpn_store(struct device *dev, struct device_attribute *attr, | |||
1863 | "0463 lpfc_soft_wwpn attribute set failed to " | 1901 | "0463 lpfc_soft_wwpn attribute set failed to " |
1864 | "reinit adapter - %d\n", stat1); | 1902 | "reinit adapter - %d\n", stat1); |
1865 | init_completion(&online_compl); | 1903 | init_completion(&online_compl); |
1866 | lpfc_workq_post_event(phba, &stat2, &online_compl, LPFC_EVT_ONLINE); | 1904 | rc = lpfc_workq_post_event(phba, &stat2, &online_compl, |
1905 | LPFC_EVT_ONLINE); | ||
1906 | if (rc == 0) | ||
1907 | return -ENOMEM; | ||
1908 | |||
1867 | wait_for_completion(&online_compl); | 1909 | wait_for_completion(&online_compl); |
1868 | if (stat2) | 1910 | if (stat2) |
1869 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 1911 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, |
@@ -1954,7 +1996,7 @@ static DEVICE_ATTR(lpfc_soft_wwnn, S_IRUGO | S_IWUSR,\ | |||
1954 | 1996 | ||
1955 | 1997 | ||
1956 | static int lpfc_poll = 0; | 1998 | static int lpfc_poll = 0; |
1957 | module_param(lpfc_poll, int, 0); | 1999 | module_param(lpfc_poll, int, S_IRUGO); |
1958 | MODULE_PARM_DESC(lpfc_poll, "FCP ring polling mode control:" | 2000 | MODULE_PARM_DESC(lpfc_poll, "FCP ring polling mode control:" |
1959 | " 0 - none," | 2001 | " 0 - none," |
1960 | " 1 - poll with interrupts enabled" | 2002 | " 1 - poll with interrupts enabled" |
@@ -1964,21 +2006,21 @@ static DEVICE_ATTR(lpfc_poll, S_IRUGO | S_IWUSR, | |||
1964 | lpfc_poll_show, lpfc_poll_store); | 2006 | lpfc_poll_show, lpfc_poll_store); |
1965 | 2007 | ||
1966 | int lpfc_sli_mode = 0; | 2008 | int lpfc_sli_mode = 0; |
1967 | module_param(lpfc_sli_mode, int, 0); | 2009 | module_param(lpfc_sli_mode, int, S_IRUGO); |
1968 | MODULE_PARM_DESC(lpfc_sli_mode, "SLI mode selector:" | 2010 | MODULE_PARM_DESC(lpfc_sli_mode, "SLI mode selector:" |
1969 | " 0 - auto (SLI-3 if supported)," | 2011 | " 0 - auto (SLI-3 if supported)," |
1970 | " 2 - select SLI-2 even on SLI-3 capable HBAs," | 2012 | " 2 - select SLI-2 even on SLI-3 capable HBAs," |
1971 | " 3 - select SLI-3"); | 2013 | " 3 - select SLI-3"); |
1972 | 2014 | ||
1973 | int lpfc_enable_npiv = 1; | 2015 | int lpfc_enable_npiv = 1; |
1974 | module_param(lpfc_enable_npiv, int, 0); | 2016 | module_param(lpfc_enable_npiv, int, S_IRUGO); |
1975 | MODULE_PARM_DESC(lpfc_enable_npiv, "Enable NPIV functionality"); | 2017 | MODULE_PARM_DESC(lpfc_enable_npiv, "Enable NPIV functionality"); |
1976 | lpfc_param_show(enable_npiv); | 2018 | lpfc_param_show(enable_npiv); |
1977 | lpfc_param_init(enable_npiv, 1, 0, 1); | 2019 | lpfc_param_init(enable_npiv, 1, 0, 1); |
1978 | static DEVICE_ATTR(lpfc_enable_npiv, S_IRUGO, lpfc_enable_npiv_show, NULL); | 2020 | static DEVICE_ATTR(lpfc_enable_npiv, S_IRUGO, lpfc_enable_npiv_show, NULL); |
1979 | 2021 | ||
1980 | int lpfc_enable_rrq; | 2022 | int lpfc_enable_rrq; |
1981 | module_param(lpfc_enable_rrq, int, 0); | 2023 | module_param(lpfc_enable_rrq, int, S_IRUGO); |
1982 | MODULE_PARM_DESC(lpfc_enable_rrq, "Enable RRQ functionality"); | 2024 | MODULE_PARM_DESC(lpfc_enable_rrq, "Enable RRQ functionality"); |
1983 | lpfc_param_show(enable_rrq); | 2025 | lpfc_param_show(enable_rrq); |
1984 | lpfc_param_init(enable_rrq, 0, 0, 1); | 2026 | lpfc_param_init(enable_rrq, 0, 0, 1); |
@@ -2040,7 +2082,7 @@ static DEVICE_ATTR(txcmplq_hw, S_IRUGO, | |||
2040 | lpfc_txcmplq_hw_show, NULL); | 2082 | lpfc_txcmplq_hw_show, NULL); |
2041 | 2083 | ||
2042 | int lpfc_iocb_cnt = 2; | 2084 | int lpfc_iocb_cnt = 2; |
2043 | module_param(lpfc_iocb_cnt, int, 1); | 2085 | module_param(lpfc_iocb_cnt, int, S_IRUGO); |
2044 | MODULE_PARM_DESC(lpfc_iocb_cnt, | 2086 | MODULE_PARM_DESC(lpfc_iocb_cnt, |
2045 | "Number of IOCBs alloc for ELS, CT, and ABTS: 1k to 5k IOCBs"); | 2087 | "Number of IOCBs alloc for ELS, CT, and ABTS: 1k to 5k IOCBs"); |
2046 | lpfc_param_show(iocb_cnt); | 2088 | lpfc_param_show(iocb_cnt); |
@@ -2192,7 +2234,7 @@ static DEVICE_ATTR(lpfc_nodev_tmo, S_IRUGO | S_IWUSR, | |||
2192 | # disappear until the timer expires. Value range is [0,255]. Default | 2234 | # disappear until the timer expires. Value range is [0,255]. Default |
2193 | # value is 30. | 2235 | # value is 30. |
2194 | */ | 2236 | */ |
2195 | module_param(lpfc_devloss_tmo, int, 0); | 2237 | module_param(lpfc_devloss_tmo, int, S_IRUGO); |
2196 | MODULE_PARM_DESC(lpfc_devloss_tmo, | 2238 | MODULE_PARM_DESC(lpfc_devloss_tmo, |
2197 | "Seconds driver will hold I/O waiting " | 2239 | "Seconds driver will hold I/O waiting " |
2198 | "for a device to come back"); | 2240 | "for a device to come back"); |
@@ -2302,7 +2344,7 @@ LPFC_VPORT_ATTR_R(peer_port_login, 0, 0, 1, | |||
2302 | # Default value of this parameter is 1. | 2344 | # Default value of this parameter is 1. |
2303 | */ | 2345 | */ |
2304 | static int lpfc_restrict_login = 1; | 2346 | static int lpfc_restrict_login = 1; |
2305 | module_param(lpfc_restrict_login, int, 0); | 2347 | module_param(lpfc_restrict_login, int, S_IRUGO); |
2306 | MODULE_PARM_DESC(lpfc_restrict_login, | 2348 | MODULE_PARM_DESC(lpfc_restrict_login, |
2307 | "Restrict virtual ports login to remote initiators."); | 2349 | "Restrict virtual ports login to remote initiators."); |
2308 | lpfc_vport_param_show(restrict_login); | 2350 | lpfc_vport_param_show(restrict_login); |
@@ -2473,7 +2515,7 @@ lpfc_topology_store(struct device *dev, struct device_attribute *attr, | |||
2473 | return -EINVAL; | 2515 | return -EINVAL; |
2474 | } | 2516 | } |
2475 | static int lpfc_topology = 0; | 2517 | static int lpfc_topology = 0; |
2476 | module_param(lpfc_topology, int, 0); | 2518 | module_param(lpfc_topology, int, S_IRUGO); |
2477 | MODULE_PARM_DESC(lpfc_topology, "Select Fibre Channel topology"); | 2519 | MODULE_PARM_DESC(lpfc_topology, "Select Fibre Channel topology"); |
2478 | lpfc_param_show(topology) | 2520 | lpfc_param_show(topology) |
2479 | lpfc_param_init(topology, 0, 0, 6) | 2521 | lpfc_param_init(topology, 0, 0, 6) |
@@ -2915,7 +2957,7 @@ lpfc_link_speed_store(struct device *dev, struct device_attribute *attr, | |||
2915 | } | 2957 | } |
2916 | 2958 | ||
2917 | static int lpfc_link_speed = 0; | 2959 | static int lpfc_link_speed = 0; |
2918 | module_param(lpfc_link_speed, int, 0); | 2960 | module_param(lpfc_link_speed, int, S_IRUGO); |
2919 | MODULE_PARM_DESC(lpfc_link_speed, "Select link speed"); | 2961 | MODULE_PARM_DESC(lpfc_link_speed, "Select link speed"); |
2920 | lpfc_param_show(link_speed) | 2962 | lpfc_param_show(link_speed) |
2921 | 2963 | ||
@@ -3043,7 +3085,7 @@ lpfc_aer_support_store(struct device *dev, struct device_attribute *attr, | |||
3043 | } | 3085 | } |
3044 | 3086 | ||
3045 | static int lpfc_aer_support = 1; | 3087 | static int lpfc_aer_support = 1; |
3046 | module_param(lpfc_aer_support, int, 1); | 3088 | module_param(lpfc_aer_support, int, S_IRUGO); |
3047 | MODULE_PARM_DESC(lpfc_aer_support, "Enable PCIe device AER support"); | 3089 | MODULE_PARM_DESC(lpfc_aer_support, "Enable PCIe device AER support"); |
3048 | lpfc_param_show(aer_support) | 3090 | lpfc_param_show(aer_support) |
3049 | 3091 | ||
@@ -3155,7 +3197,7 @@ LPFC_VPORT_ATTR_RW(use_adisc, 0, 0, 1, | |||
3155 | # The value is set in milliseconds. | 3197 | # The value is set in milliseconds. |
3156 | */ | 3198 | */ |
3157 | static int lpfc_max_scsicmpl_time; | 3199 | static int lpfc_max_scsicmpl_time; |
3158 | module_param(lpfc_max_scsicmpl_time, int, 0); | 3200 | module_param(lpfc_max_scsicmpl_time, int, S_IRUGO); |
3159 | MODULE_PARM_DESC(lpfc_max_scsicmpl_time, | 3201 | MODULE_PARM_DESC(lpfc_max_scsicmpl_time, |
3160 | "Use command completion time to control queue depth"); | 3202 | "Use command completion time to control queue depth"); |
3161 | lpfc_vport_param_show(max_scsicmpl_time); | 3203 | lpfc_vport_param_show(max_scsicmpl_time); |
@@ -3331,7 +3373,7 @@ LPFC_ATTR_R(enable_bg, 0, 0, 1, "Enable BlockGuard Support"); | |||
3331 | */ | 3373 | */ |
3332 | unsigned int lpfc_prot_mask = SHOST_DIF_TYPE1_PROTECTION; | 3374 | unsigned int lpfc_prot_mask = SHOST_DIF_TYPE1_PROTECTION; |
3333 | 3375 | ||
3334 | module_param(lpfc_prot_mask, uint, 0); | 3376 | module_param(lpfc_prot_mask, uint, S_IRUGO); |
3335 | MODULE_PARM_DESC(lpfc_prot_mask, "host protection mask"); | 3377 | MODULE_PARM_DESC(lpfc_prot_mask, "host protection mask"); |
3336 | 3378 | ||
3337 | /* | 3379 | /* |
@@ -3343,9 +3385,28 @@ MODULE_PARM_DESC(lpfc_prot_mask, "host protection mask"); | |||
3343 | # | 3385 | # |
3344 | */ | 3386 | */ |
3345 | unsigned char lpfc_prot_guard = SHOST_DIX_GUARD_IP; | 3387 | unsigned char lpfc_prot_guard = SHOST_DIX_GUARD_IP; |
3346 | module_param(lpfc_prot_guard, byte, 0); | 3388 | module_param(lpfc_prot_guard, byte, S_IRUGO); |
3347 | MODULE_PARM_DESC(lpfc_prot_guard, "host protection guard type"); | 3389 | MODULE_PARM_DESC(lpfc_prot_guard, "host protection guard type"); |
3348 | 3390 | ||
3391 | /* | ||
3392 | * Delay initial NPort discovery when Clean Address bit is cleared in | ||
3393 | * FLOGI/FDISC accept and FCID/Fabric name/Fabric portname is changed. | ||
3394 | * This parameter can have value 0 or 1. | ||
3395 | * When this parameter is set to 0, no delay is added to the initial | ||
3396 | * discovery. | ||
3397 | * When this parameter is set to non-zero value, initial Nport discovery is | ||
3398 | * delayed by ra_tov seconds when Clean Address bit is cleared in FLOGI/FDISC | ||
3399 | * accept and FCID/Fabric name/Fabric portname is changed. | ||
3400 | * Driver always delay Nport discovery for subsequent FLOGI/FDISC completion | ||
3401 | * when Clean Address bit is cleared in FLOGI/FDISC | ||
3402 | * accept and FCID/Fabric name/Fabric portname is changed. | ||
3403 | * Default value is 0. | ||
3404 | */ | ||
3405 | int lpfc_delay_discovery; | ||
3406 | module_param(lpfc_delay_discovery, int, S_IRUGO); | ||
3407 | MODULE_PARM_DESC(lpfc_delay_discovery, | ||
3408 | "Delay NPort discovery when Clean Address bit is cleared. " | ||
3409 | "Allowed values: 0,1."); | ||
3349 | 3410 | ||
3350 | /* | 3411 | /* |
3351 | * lpfc_sg_seg_cnt - Initial Maximum DMA Segment Count | 3412 | * lpfc_sg_seg_cnt - Initial Maximum DMA Segment Count |
@@ -3437,6 +3498,7 @@ struct device_attribute *lpfc_hba_attrs[] = { | |||
3437 | &dev_attr_txcmplq_hw, | 3498 | &dev_attr_txcmplq_hw, |
3438 | &dev_attr_lpfc_fips_level, | 3499 | &dev_attr_lpfc_fips_level, |
3439 | &dev_attr_lpfc_fips_rev, | 3500 | &dev_attr_lpfc_fips_rev, |
3501 | &dev_attr_lpfc_dss, | ||
3440 | NULL, | 3502 | NULL, |
3441 | }; | 3503 | }; |
3442 | 3504 | ||
@@ -4639,6 +4701,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) | |||
4639 | lpfc_aer_support_init(phba, lpfc_aer_support); | 4701 | lpfc_aer_support_init(phba, lpfc_aer_support); |
4640 | lpfc_suppress_link_up_init(phba, lpfc_suppress_link_up); | 4702 | lpfc_suppress_link_up_init(phba, lpfc_suppress_link_up); |
4641 | lpfc_iocb_cnt_init(phba, lpfc_iocb_cnt); | 4703 | lpfc_iocb_cnt_init(phba, lpfc_iocb_cnt); |
4704 | phba->cfg_enable_dss = 1; | ||
4642 | return; | 4705 | return; |
4643 | } | 4706 | } |
4644 | 4707 | ||
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 17fde522c84a..3d40023f4804 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
@@ -53,9 +53,9 @@ void lpfc_unreg_vpi(struct lpfc_hba *, uint16_t, LPFC_MBOXQ_t *); | |||
53 | void lpfc_init_link(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t); | 53 | void lpfc_init_link(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t); |
54 | void lpfc_request_features(struct lpfc_hba *, struct lpfcMboxq *); | 54 | void lpfc_request_features(struct lpfc_hba *, struct lpfcMboxq *); |
55 | void lpfc_supported_pages(struct lpfcMboxq *); | 55 | void lpfc_supported_pages(struct lpfcMboxq *); |
56 | void lpfc_sli4_params(struct lpfcMboxq *); | 56 | void lpfc_pc_sli4_params(struct lpfcMboxq *); |
57 | int lpfc_pc_sli4_params_get(struct lpfc_hba *, LPFC_MBOXQ_t *); | 57 | int lpfc_pc_sli4_params_get(struct lpfc_hba *, LPFC_MBOXQ_t *); |
58 | 58 | int lpfc_get_sli4_parameters(struct lpfc_hba *, LPFC_MBOXQ_t *); | |
59 | struct lpfc_vport *lpfc_find_vport_by_did(struct lpfc_hba *, uint32_t); | 59 | struct lpfc_vport *lpfc_find_vport_by_did(struct lpfc_hba *, uint32_t); |
60 | void lpfc_cleanup_rcv_buffers(struct lpfc_vport *); | 60 | void lpfc_cleanup_rcv_buffers(struct lpfc_vport *); |
61 | void lpfc_rcv_seq_check_edtov(struct lpfc_vport *); | 61 | void lpfc_rcv_seq_check_edtov(struct lpfc_vport *); |
@@ -167,6 +167,8 @@ int lpfc_ns_cmd(struct lpfc_vport *, int, uint8_t, uint32_t); | |||
167 | int lpfc_fdmi_cmd(struct lpfc_vport *, struct lpfc_nodelist *, int); | 167 | int lpfc_fdmi_cmd(struct lpfc_vport *, struct lpfc_nodelist *, int); |
168 | void lpfc_fdmi_tmo(unsigned long); | 168 | void lpfc_fdmi_tmo(unsigned long); |
169 | void lpfc_fdmi_timeout_handler(struct lpfc_vport *); | 169 | void lpfc_fdmi_timeout_handler(struct lpfc_vport *); |
170 | void lpfc_delayed_disc_tmo(unsigned long); | ||
171 | void lpfc_delayed_disc_timeout_handler(struct lpfc_vport *); | ||
170 | 172 | ||
171 | int lpfc_config_port_prep(struct lpfc_hba *); | 173 | int lpfc_config_port_prep(struct lpfc_hba *); |
172 | int lpfc_config_port_post(struct lpfc_hba *); | 174 | int lpfc_config_port_post(struct lpfc_hba *); |
@@ -341,6 +343,7 @@ extern struct fc_function_template lpfc_transport_functions; | |||
341 | extern struct fc_function_template lpfc_vport_transport_functions; | 343 | extern struct fc_function_template lpfc_vport_transport_functions; |
342 | extern int lpfc_sli_mode; | 344 | extern int lpfc_sli_mode; |
343 | extern int lpfc_enable_npiv; | 345 | extern int lpfc_enable_npiv; |
346 | extern int lpfc_delay_discovery; | ||
344 | 347 | ||
345 | int lpfc_vport_symbolic_node_name(struct lpfc_vport *, char *, size_t); | 348 | int lpfc_vport_symbolic_node_name(struct lpfc_vport *, char *, size_t); |
346 | int lpfc_vport_symbolic_port_name(struct lpfc_vport *, char *, size_t); | 349 | int lpfc_vport_symbolic_port_name(struct lpfc_vport *, char *, size_t); |
@@ -423,6 +426,6 @@ int lpfc_send_rrq(struct lpfc_hba *, struct lpfc_node_rrq *); | |||
423 | int lpfc_set_rrq_active(struct lpfc_hba *, struct lpfc_nodelist *, | 426 | int lpfc_set_rrq_active(struct lpfc_hba *, struct lpfc_nodelist *, |
424 | uint16_t, uint16_t, uint16_t); | 427 | uint16_t, uint16_t, uint16_t); |
425 | void lpfc_cleanup_wt_rrqs(struct lpfc_hba *); | 428 | void lpfc_cleanup_wt_rrqs(struct lpfc_hba *); |
426 | void lpfc_cleanup_vports_rrqs(struct lpfc_vport *); | 429 | void lpfc_cleanup_vports_rrqs(struct lpfc_vport *, struct lpfc_nodelist *); |
427 | struct lpfc_node_rrq *lpfc_get_active_rrq(struct lpfc_vport *, uint16_t, | 430 | struct lpfc_node_rrq *lpfc_get_active_rrq(struct lpfc_vport *, uint16_t, |
428 | uint32_t); | 431 | uint32_t); |
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index c004fa9a681e..d9edfd90d7ff 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c | |||
@@ -1738,6 +1738,55 @@ fdmi_cmd_exit: | |||
1738 | return 1; | 1738 | return 1; |
1739 | } | 1739 | } |
1740 | 1740 | ||
1741 | /** | ||
1742 | * lpfc_delayed_disc_tmo - Timeout handler for delayed discovery timer. | ||
1743 | * @ptr - Context object of the timer. | ||
1744 | * | ||
1745 | * This function set the WORKER_DELAYED_DISC_TMO flag and wake up | ||
1746 | * the worker thread. | ||
1747 | **/ | ||
1748 | void | ||
1749 | lpfc_delayed_disc_tmo(unsigned long ptr) | ||
1750 | { | ||
1751 | struct lpfc_vport *vport = (struct lpfc_vport *)ptr; | ||
1752 | struct lpfc_hba *phba = vport->phba; | ||
1753 | uint32_t tmo_posted; | ||
1754 | unsigned long iflag; | ||
1755 | |||
1756 | spin_lock_irqsave(&vport->work_port_lock, iflag); | ||
1757 | tmo_posted = vport->work_port_events & WORKER_DELAYED_DISC_TMO; | ||
1758 | if (!tmo_posted) | ||
1759 | vport->work_port_events |= WORKER_DELAYED_DISC_TMO; | ||
1760 | spin_unlock_irqrestore(&vport->work_port_lock, iflag); | ||
1761 | |||
1762 | if (!tmo_posted) | ||
1763 | lpfc_worker_wake_up(phba); | ||
1764 | return; | ||
1765 | } | ||
1766 | |||
1767 | /** | ||
1768 | * lpfc_delayed_disc_timeout_handler - Function called by worker thread to | ||
1769 | * handle delayed discovery. | ||
1770 | * @vport: pointer to a host virtual N_Port data structure. | ||
1771 | * | ||
1772 | * This function start nport discovery of the vport. | ||
1773 | **/ | ||
1774 | void | ||
1775 | lpfc_delayed_disc_timeout_handler(struct lpfc_vport *vport) | ||
1776 | { | ||
1777 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
1778 | |||
1779 | spin_lock_irq(shost->host_lock); | ||
1780 | if (!(vport->fc_flag & FC_DISC_DELAYED)) { | ||
1781 | spin_unlock_irq(shost->host_lock); | ||
1782 | return; | ||
1783 | } | ||
1784 | vport->fc_flag &= ~FC_DISC_DELAYED; | ||
1785 | spin_unlock_irq(shost->host_lock); | ||
1786 | |||
1787 | lpfc_do_scr_ns_plogi(vport->phba, vport); | ||
1788 | } | ||
1789 | |||
1741 | void | 1790 | void |
1742 | lpfc_fdmi_tmo(unsigned long ptr) | 1791 | lpfc_fdmi_tmo(unsigned long ptr) |
1743 | { | 1792 | { |
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index a80d938fafc9..a753581509d6 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2007-2009 Emulex. All rights reserved. * | 4 | * Copyright (C) 2007-2011 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * * | 7 | * * |
@@ -57,8 +57,8 @@ | |||
57 | * # mount -t debugfs none /sys/kernel/debug | 57 | * # mount -t debugfs none /sys/kernel/debug |
58 | * | 58 | * |
59 | * The lpfc debugfs directory hierarchy is: | 59 | * The lpfc debugfs directory hierarchy is: |
60 | * lpfc/lpfcX/vportY | 60 | * /sys/kernel/debug/lpfc/fnX/vportY |
61 | * where X is the lpfc hba unique_id | 61 | * where X is the lpfc hba function unique_id |
62 | * where Y is the vport VPI on that hba | 62 | * where Y is the vport VPI on that hba |
63 | * | 63 | * |
64 | * Debugging services available per vport: | 64 | * Debugging services available per vport: |
@@ -82,52 +82,34 @@ | |||
82 | * the HBA. X MUST also be a power of 2. | 82 | * the HBA. X MUST also be a power of 2. |
83 | */ | 83 | */ |
84 | static int lpfc_debugfs_enable = 1; | 84 | static int lpfc_debugfs_enable = 1; |
85 | module_param(lpfc_debugfs_enable, int, 0); | 85 | module_param(lpfc_debugfs_enable, int, S_IRUGO); |
86 | MODULE_PARM_DESC(lpfc_debugfs_enable, "Enable debugfs services"); | 86 | MODULE_PARM_DESC(lpfc_debugfs_enable, "Enable debugfs services"); |
87 | 87 | ||
88 | /* This MUST be a power of 2 */ | 88 | /* This MUST be a power of 2 */ |
89 | static int lpfc_debugfs_max_disc_trc; | 89 | static int lpfc_debugfs_max_disc_trc; |
90 | module_param(lpfc_debugfs_max_disc_trc, int, 0); | 90 | module_param(lpfc_debugfs_max_disc_trc, int, S_IRUGO); |
91 | MODULE_PARM_DESC(lpfc_debugfs_max_disc_trc, | 91 | MODULE_PARM_DESC(lpfc_debugfs_max_disc_trc, |
92 | "Set debugfs discovery trace depth"); | 92 | "Set debugfs discovery trace depth"); |
93 | 93 | ||
94 | /* This MUST be a power of 2 */ | 94 | /* This MUST be a power of 2 */ |
95 | static int lpfc_debugfs_max_slow_ring_trc; | 95 | static int lpfc_debugfs_max_slow_ring_trc; |
96 | module_param(lpfc_debugfs_max_slow_ring_trc, int, 0); | 96 | module_param(lpfc_debugfs_max_slow_ring_trc, int, S_IRUGO); |
97 | MODULE_PARM_DESC(lpfc_debugfs_max_slow_ring_trc, | 97 | MODULE_PARM_DESC(lpfc_debugfs_max_slow_ring_trc, |
98 | "Set debugfs slow ring trace depth"); | 98 | "Set debugfs slow ring trace depth"); |
99 | 99 | ||
100 | static int lpfc_debugfs_mask_disc_trc; | 100 | static int lpfc_debugfs_mask_disc_trc; |
101 | module_param(lpfc_debugfs_mask_disc_trc, int, 0); | 101 | module_param(lpfc_debugfs_mask_disc_trc, int, S_IRUGO); |
102 | MODULE_PARM_DESC(lpfc_debugfs_mask_disc_trc, | 102 | MODULE_PARM_DESC(lpfc_debugfs_mask_disc_trc, |
103 | "Set debugfs discovery trace mask"); | 103 | "Set debugfs discovery trace mask"); |
104 | 104 | ||
105 | #include <linux/debugfs.h> | 105 | #include <linux/debugfs.h> |
106 | 106 | ||
107 | /* size of output line, for discovery_trace and slow_ring_trace */ | ||
108 | #define LPFC_DEBUG_TRC_ENTRY_SIZE 100 | ||
109 | |||
110 | /* nodelist output buffer size */ | ||
111 | #define LPFC_NODELIST_SIZE 8192 | ||
112 | #define LPFC_NODELIST_ENTRY_SIZE 120 | ||
113 | |||
114 | /* dumpHBASlim output buffer size */ | ||
115 | #define LPFC_DUMPHBASLIM_SIZE 4096 | ||
116 | |||
117 | /* dumpHostSlim output buffer size */ | ||
118 | #define LPFC_DUMPHOSTSLIM_SIZE 4096 | ||
119 | |||
120 | /* hbqinfo output buffer size */ | ||
121 | #define LPFC_HBQINFO_SIZE 8192 | ||
122 | |||
123 | struct lpfc_debug { | ||
124 | char *buffer; | ||
125 | int len; | ||
126 | }; | ||
127 | |||
128 | static atomic_t lpfc_debugfs_seq_trc_cnt = ATOMIC_INIT(0); | 107 | static atomic_t lpfc_debugfs_seq_trc_cnt = ATOMIC_INIT(0); |
129 | static unsigned long lpfc_debugfs_start_time = 0L; | 108 | static unsigned long lpfc_debugfs_start_time = 0L; |
130 | 109 | ||
110 | /* iDiag */ | ||
111 | static struct lpfc_idiag idiag; | ||
112 | |||
131 | /** | 113 | /** |
132 | * lpfc_debugfs_disc_trc_data - Dump discovery logging to a buffer | 114 | * lpfc_debugfs_disc_trc_data - Dump discovery logging to a buffer |
133 | * @vport: The vport to gather the log info from. | 115 | * @vport: The vport to gather the log info from. |
@@ -996,8 +978,6 @@ lpfc_debugfs_dumpDataDif_write(struct file *file, const char __user *buf, | |||
996 | return nbytes; | 978 | return nbytes; |
997 | } | 979 | } |
998 | 980 | ||
999 | |||
1000 | |||
1001 | /** | 981 | /** |
1002 | * lpfc_debugfs_nodelist_open - Open the nodelist debugfs file | 982 | * lpfc_debugfs_nodelist_open - Open the nodelist debugfs file |
1003 | * @inode: The inode pointer that contains a vport pointer. | 983 | * @inode: The inode pointer that contains a vport pointer. |
@@ -1099,6 +1079,7 @@ lpfc_debugfs_read(struct file *file, char __user *buf, | |||
1099 | size_t nbytes, loff_t *ppos) | 1079 | size_t nbytes, loff_t *ppos) |
1100 | { | 1080 | { |
1101 | struct lpfc_debug *debug = file->private_data; | 1081 | struct lpfc_debug *debug = file->private_data; |
1082 | |||
1102 | return simple_read_from_buffer(buf, nbytes, ppos, debug->buffer, | 1083 | return simple_read_from_buffer(buf, nbytes, ppos, debug->buffer, |
1103 | debug->len); | 1084 | debug->len); |
1104 | } | 1085 | } |
@@ -1137,6 +1118,776 @@ lpfc_debugfs_dumpDataDif_release(struct inode *inode, struct file *file) | |||
1137 | return 0; | 1118 | return 0; |
1138 | } | 1119 | } |
1139 | 1120 | ||
1121 | /* | ||
1122 | * iDiag debugfs file access methods | ||
1123 | */ | ||
1124 | |||
1125 | /* | ||
1126 | * iDiag PCI config space register access methods: | ||
1127 | * | ||
1128 | * The PCI config space register accessees of read, write, read-modify-write | ||
1129 | * for set bits, and read-modify-write for clear bits to SLI4 PCI functions | ||
1130 | * are provided. In the proper SLI4 PCI function's debugfs iDiag directory, | ||
1131 | * | ||
1132 | * /sys/kernel/debug/lpfc/fn<#>/iDiag | ||
1133 | * | ||
1134 | * the access is through the debugfs entry pciCfg: | ||
1135 | * | ||
1136 | * 1. For PCI config space register read access, there are two read methods: | ||
1137 | * A) read a single PCI config space register in the size of a byte | ||
1138 | * (8 bits), a word (16 bits), or a dword (32 bits); or B) browse through | ||
1139 | * the 4K extended PCI config space. | ||
1140 | * | ||
1141 | * A) Read a single PCI config space register consists of two steps: | ||
1142 | * | ||
1143 | * Step-1: Set up PCI config space register read command, the command | ||
1144 | * syntax is, | ||
1145 | * | ||
1146 | * echo 1 <where> <count> > pciCfg | ||
1147 | * | ||
1148 | * where, 1 is the iDiag command for PCI config space read, <where> is the | ||
1149 | * offset from the beginning of the device's PCI config space to read from, | ||
1150 | * and <count> is the size of PCI config space register data to read back, | ||
1151 | * it will be 1 for reading a byte (8 bits), 2 for reading a word (16 bits | ||
1152 | * or 2 bytes), or 4 for reading a dword (32 bits or 4 bytes). | ||
1153 | * | ||
1154 | * Setp-2: Perform the debugfs read operation to execute the idiag command | ||
1155 | * set up in Step-1, | ||
1156 | * | ||
1157 | * cat pciCfg | ||
1158 | * | ||
1159 | * Examples: | ||
1160 | * To read PCI device's vendor-id and device-id from PCI config space, | ||
1161 | * | ||
1162 | * echo 1 0 4 > pciCfg | ||
1163 | * cat pciCfg | ||
1164 | * | ||
1165 | * To read PCI device's currnt command from config space, | ||
1166 | * | ||
1167 | * echo 1 4 2 > pciCfg | ||
1168 | * cat pciCfg | ||
1169 | * | ||
1170 | * B) Browse through the entire 4K extended PCI config space also consists | ||
1171 | * of two steps: | ||
1172 | * | ||
1173 | * Step-1: Set up PCI config space register browsing command, the command | ||
1174 | * syntax is, | ||
1175 | * | ||
1176 | * echo 1 0 4096 > pciCfg | ||
1177 | * | ||
1178 | * where, 1 is the iDiag command for PCI config space read, 0 must be used | ||
1179 | * as the offset for PCI config space register browse, and 4096 must be | ||
1180 | * used as the count for PCI config space register browse. | ||
1181 | * | ||
1182 | * Step-2: Repeately issue the debugfs read operation to browse through | ||
1183 | * the entire PCI config space registers: | ||
1184 | * | ||
1185 | * cat pciCfg | ||
1186 | * cat pciCfg | ||
1187 | * cat pciCfg | ||
1188 | * ... | ||
1189 | * | ||
1190 | * When browsing to the end of the 4K PCI config space, the browse method | ||
1191 | * shall wrap around to start reading from beginning again, and again... | ||
1192 | * | ||
1193 | * 2. For PCI config space register write access, it supports a single PCI | ||
1194 | * config space register write in the size of a byte (8 bits), a word | ||
1195 | * (16 bits), or a dword (32 bits). The command syntax is, | ||
1196 | * | ||
1197 | * echo 2 <where> <count> <value> > pciCfg | ||
1198 | * | ||
1199 | * where, 2 is the iDiag command for PCI config space write, <where> is | ||
1200 | * the offset from the beginning of the device's PCI config space to write | ||
1201 | * into, <count> is the size of data to write into the PCI config space, | ||
1202 | * it will be 1 for writing a byte (8 bits), 2 for writing a word (16 bits | ||
1203 | * or 2 bytes), or 4 for writing a dword (32 bits or 4 bytes), and <value> | ||
1204 | * is the data to be written into the PCI config space register at the | ||
1205 | * offset. | ||
1206 | * | ||
1207 | * Examples: | ||
1208 | * To disable PCI device's interrupt assertion, | ||
1209 | * | ||
1210 | * 1) Read in device's PCI config space register command field <cmd>: | ||
1211 | * | ||
1212 | * echo 1 4 2 > pciCfg | ||
1213 | * cat pciCfg | ||
1214 | * | ||
1215 | * 2) Set bit 10 (Interrupt Disable bit) in the <cmd>: | ||
1216 | * | ||
1217 | * <cmd> = <cmd> | (1 < 10) | ||
1218 | * | ||
1219 | * 3) Write the modified command back: | ||
1220 | * | ||
1221 | * echo 2 4 2 <cmd> > pciCfg | ||
1222 | * | ||
1223 | * 3. For PCI config space register set bits access, it supports a single PCI | ||
1224 | * config space register set bits in the size of a byte (8 bits), a word | ||
1225 | * (16 bits), or a dword (32 bits). The command syntax is, | ||
1226 | * | ||
1227 | * echo 3 <where> <count> <bitmask> > pciCfg | ||
1228 | * | ||
1229 | * where, 3 is the iDiag command for PCI config space set bits, <where> is | ||
1230 | * the offset from the beginning of the device's PCI config space to set | ||
1231 | * bits into, <count> is the size of the bitmask to set into the PCI config | ||
1232 | * space, it will be 1 for setting a byte (8 bits), 2 for setting a word | ||
1233 | * (16 bits or 2 bytes), or 4 for setting a dword (32 bits or 4 bytes), and | ||
1234 | * <bitmask> is the bitmask, indicating the bits to be set into the PCI | ||
1235 | * config space register at the offset. The logic performed to the content | ||
1236 | * of the PCI config space register, regval, is, | ||
1237 | * | ||
1238 | * regval |= <bitmask> | ||
1239 | * | ||
1240 | * 4. For PCI config space register clear bits access, it supports a single | ||
1241 | * PCI config space register clear bits in the size of a byte (8 bits), | ||
1242 | * a word (16 bits), or a dword (32 bits). The command syntax is, | ||
1243 | * | ||
1244 | * echo 4 <where> <count> <bitmask> > pciCfg | ||
1245 | * | ||
1246 | * where, 4 is the iDiag command for PCI config space clear bits, <where> | ||
1247 | * is the offset from the beginning of the device's PCI config space to | ||
1248 | * clear bits from, <count> is the size of the bitmask to set into the PCI | ||
1249 | * config space, it will be 1 for setting a byte (8 bits), 2 for setting | ||
1250 | * a word(16 bits or 2 bytes), or 4 for setting a dword (32 bits or 4 | ||
1251 | * bytes), and <bitmask> is the bitmask, indicating the bits to be cleared | ||
1252 | * from the PCI config space register at the offset. the logic performed | ||
1253 | * to the content of the PCI config space register, regval, is, | ||
1254 | * | ||
1255 | * regval &= ~<bitmask> | ||
1256 | * | ||
1257 | * Note, for all single register read, write, set bits, or clear bits access, | ||
1258 | * the offset (<where>) must be aligned with the size of the data: | ||
1259 | * | ||
1260 | * For data size of byte (8 bits), the offset must be aligned to the byte | ||
1261 | * boundary; for data size of word (16 bits), the offset must be aligned | ||
1262 | * to the word boundary; while for data size of dword (32 bits), the offset | ||
1263 | * must be aligned to the dword boundary. Otherwise, the interface will | ||
1264 | * return the error: | ||
1265 | * | ||
1266 | * "-bash: echo: write error: Invalid argument". | ||
1267 | * | ||
1268 | * For example: | ||
1269 | * | ||
1270 | * echo 1 2 4 > pciCfg | ||
1271 | * -bash: echo: write error: Invalid argument | ||
1272 | * | ||
1273 | * Note also, all of the numbers in the command fields for all read, write, | ||
1274 | * set bits, and clear bits PCI config space register command fields can be | ||
1275 | * either decimal or hex. | ||
1276 | * | ||
1277 | * For example, | ||
1278 | * echo 1 0 4096 > pciCfg | ||
1279 | * | ||
1280 | * will be the same as | ||
1281 | * echo 1 0 0x1000 > pciCfg | ||
1282 | * | ||
1283 | * And, | ||
1284 | * echo 2 155 1 10 > pciCfg | ||
1285 | * | ||
1286 | * will be | ||
1287 | * echo 2 0x9b 1 0xa > pciCfg | ||
1288 | */ | ||
1289 | |||
1290 | /** | ||
1291 | * lpfc_idiag_cmd_get - Get and parse idiag debugfs comands from user space | ||
1292 | * @buf: The pointer to the user space buffer. | ||
1293 | * @nbytes: The number of bytes in the user space buffer. | ||
1294 | * @idiag_cmd: pointer to the idiag command struct. | ||
1295 | * | ||
1296 | * This routine reads data from debugfs user space buffer and parses the | ||
1297 | * buffer for getting the idiag command and arguments. The while space in | ||
1298 | * between the set of data is used as the parsing separator. | ||
1299 | * | ||
1300 | * This routine returns 0 when successful, it returns proper error code | ||
1301 | * back to the user space in error conditions. | ||
1302 | */ | ||
1303 | static int lpfc_idiag_cmd_get(const char __user *buf, size_t nbytes, | ||
1304 | struct lpfc_idiag_cmd *idiag_cmd) | ||
1305 | { | ||
1306 | char mybuf[64]; | ||
1307 | char *pbuf, *step_str; | ||
1308 | int bsize, i; | ||
1309 | |||
1310 | /* Protect copy from user */ | ||
1311 | if (!access_ok(VERIFY_READ, buf, nbytes)) | ||
1312 | return -EFAULT; | ||
1313 | |||
1314 | memset(mybuf, 0, sizeof(mybuf)); | ||
1315 | memset(idiag_cmd, 0, sizeof(*idiag_cmd)); | ||
1316 | bsize = min(nbytes, (sizeof(mybuf)-1)); | ||
1317 | |||
1318 | if (copy_from_user(mybuf, buf, bsize)) | ||
1319 | return -EFAULT; | ||
1320 | pbuf = &mybuf[0]; | ||
1321 | step_str = strsep(&pbuf, "\t "); | ||
1322 | |||
1323 | /* The opcode must present */ | ||
1324 | if (!step_str) | ||
1325 | return -EINVAL; | ||
1326 | |||
1327 | idiag_cmd->opcode = simple_strtol(step_str, NULL, 0); | ||
1328 | if (idiag_cmd->opcode == 0) | ||
1329 | return -EINVAL; | ||
1330 | |||
1331 | for (i = 0; i < LPFC_IDIAG_CMD_DATA_SIZE; i++) { | ||
1332 | step_str = strsep(&pbuf, "\t "); | ||
1333 | if (!step_str) | ||
1334 | return 0; | ||
1335 | idiag_cmd->data[i] = simple_strtol(step_str, NULL, 0); | ||
1336 | } | ||
1337 | return 0; | ||
1338 | } | ||
1339 | |||
1340 | /** | ||
1341 | * lpfc_idiag_open - idiag open debugfs | ||
1342 | * @inode: The inode pointer that contains a pointer to phba. | ||
1343 | * @file: The file pointer to attach the file operation. | ||
1344 | * | ||
1345 | * Description: | ||
1346 | * This routine is the entry point for the debugfs open file operation. It | ||
1347 | * gets the reference to phba from the i_private field in @inode, it then | ||
1348 | * allocates buffer for the file operation, performs the necessary PCI config | ||
1349 | * space read into the allocated buffer according to the idiag user command | ||
1350 | * setup, and then returns a pointer to buffer in the private_data field in | ||
1351 | * @file. | ||
1352 | * | ||
1353 | * Returns: | ||
1354 | * This function returns zero if successful. On error it will return an | ||
1355 | * negative error value. | ||
1356 | **/ | ||
1357 | static int | ||
1358 | lpfc_idiag_open(struct inode *inode, struct file *file) | ||
1359 | { | ||
1360 | struct lpfc_debug *debug; | ||
1361 | |||
1362 | debug = kmalloc(sizeof(*debug), GFP_KERNEL); | ||
1363 | if (!debug) | ||
1364 | return -ENOMEM; | ||
1365 | |||
1366 | debug->i_private = inode->i_private; | ||
1367 | debug->buffer = NULL; | ||
1368 | file->private_data = debug; | ||
1369 | |||
1370 | return 0; | ||
1371 | } | ||
1372 | |||
1373 | /** | ||
1374 | * lpfc_idiag_release - Release idiag access file operation | ||
1375 | * @inode: The inode pointer that contains a vport pointer. (unused) | ||
1376 | * @file: The file pointer that contains the buffer to release. | ||
1377 | * | ||
1378 | * Description: | ||
1379 | * This routine is the generic release routine for the idiag access file | ||
1380 | * operation, it frees the buffer that was allocated when the debugfs file | ||
1381 | * was opened. | ||
1382 | * | ||
1383 | * Returns: | ||
1384 | * This function returns zero. | ||
1385 | **/ | ||
1386 | static int | ||
1387 | lpfc_idiag_release(struct inode *inode, struct file *file) | ||
1388 | { | ||
1389 | struct lpfc_debug *debug = file->private_data; | ||
1390 | |||
1391 | /* Free the buffers to the file operation */ | ||
1392 | kfree(debug->buffer); | ||
1393 | kfree(debug); | ||
1394 | |||
1395 | return 0; | ||
1396 | } | ||
1397 | |||
1398 | /** | ||
1399 | * lpfc_idiag_cmd_release - Release idiag cmd access file operation | ||
1400 | * @inode: The inode pointer that contains a vport pointer. (unused) | ||
1401 | * @file: The file pointer that contains the buffer to release. | ||
1402 | * | ||
1403 | * Description: | ||
1404 | * This routine frees the buffer that was allocated when the debugfs file | ||
1405 | * was opened. It also reset the fields in the idiag command struct in the | ||
1406 | * case the command is not continuous browsing of the data structure. | ||
1407 | * | ||
1408 | * Returns: | ||
1409 | * This function returns zero. | ||
1410 | **/ | ||
1411 | static int | ||
1412 | lpfc_idiag_cmd_release(struct inode *inode, struct file *file) | ||
1413 | { | ||
1414 | struct lpfc_debug *debug = file->private_data; | ||
1415 | |||
1416 | /* Read PCI config register, if not read all, clear command fields */ | ||
1417 | if ((debug->op == LPFC_IDIAG_OP_RD) && | ||
1418 | (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_RD)) | ||
1419 | if ((idiag.cmd.data[1] == sizeof(uint8_t)) || | ||
1420 | (idiag.cmd.data[1] == sizeof(uint16_t)) || | ||
1421 | (idiag.cmd.data[1] == sizeof(uint32_t))) | ||
1422 | memset(&idiag, 0, sizeof(idiag)); | ||
1423 | |||
1424 | /* Write PCI config register, clear command fields */ | ||
1425 | if ((debug->op == LPFC_IDIAG_OP_WR) && | ||
1426 | (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR)) | ||
1427 | memset(&idiag, 0, sizeof(idiag)); | ||
1428 | |||
1429 | /* Free the buffers to the file operation */ | ||
1430 | kfree(debug->buffer); | ||
1431 | kfree(debug); | ||
1432 | |||
1433 | return 0; | ||
1434 | } | ||
1435 | |||
1436 | /** | ||
1437 | * lpfc_idiag_pcicfg_read - idiag debugfs read pcicfg | ||
1438 | * @file: The file pointer to read from. | ||
1439 | * @buf: The buffer to copy the data to. | ||
1440 | * @nbytes: The number of bytes to read. | ||
1441 | * @ppos: The position in the file to start reading from. | ||
1442 | * | ||
1443 | * Description: | ||
1444 | * This routine reads data from the @phba pci config space according to the | ||
1445 | * idiag command, and copies to user @buf. Depending on the PCI config space | ||
1446 | * read command setup, it does either a single register read of a byte | ||
1447 | * (8 bits), a word (16 bits), or a dword (32 bits) or browsing through all | ||
1448 | * registers from the 4K extended PCI config space. | ||
1449 | * | ||
1450 | * Returns: | ||
1451 | * This function returns the amount of data that was read (this could be less | ||
1452 | * than @nbytes if the end of the file was reached) or a negative error value. | ||
1453 | **/ | ||
1454 | static ssize_t | ||
1455 | lpfc_idiag_pcicfg_read(struct file *file, char __user *buf, size_t nbytes, | ||
1456 | loff_t *ppos) | ||
1457 | { | ||
1458 | struct lpfc_debug *debug = file->private_data; | ||
1459 | struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private; | ||
1460 | int offset_label, offset, len = 0, index = LPFC_PCI_CFG_RD_SIZE; | ||
1461 | int where, count; | ||
1462 | char *pbuffer; | ||
1463 | struct pci_dev *pdev; | ||
1464 | uint32_t u32val; | ||
1465 | uint16_t u16val; | ||
1466 | uint8_t u8val; | ||
1467 | |||
1468 | pdev = phba->pcidev; | ||
1469 | if (!pdev) | ||
1470 | return 0; | ||
1471 | |||
1472 | /* This is a user read operation */ | ||
1473 | debug->op = LPFC_IDIAG_OP_RD; | ||
1474 | |||
1475 | if (!debug->buffer) | ||
1476 | debug->buffer = kmalloc(LPFC_PCI_CFG_SIZE, GFP_KERNEL); | ||
1477 | if (!debug->buffer) | ||
1478 | return 0; | ||
1479 | pbuffer = debug->buffer; | ||
1480 | |||
1481 | if (*ppos) | ||
1482 | return 0; | ||
1483 | |||
1484 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_RD) { | ||
1485 | where = idiag.cmd.data[0]; | ||
1486 | count = idiag.cmd.data[1]; | ||
1487 | } else | ||
1488 | return 0; | ||
1489 | |||
1490 | /* Read single PCI config space register */ | ||
1491 | switch (count) { | ||
1492 | case SIZE_U8: /* byte (8 bits) */ | ||
1493 | pci_read_config_byte(pdev, where, &u8val); | ||
1494 | len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, | ||
1495 | "%03x: %02x\n", where, u8val); | ||
1496 | break; | ||
1497 | case SIZE_U16: /* word (16 bits) */ | ||
1498 | pci_read_config_word(pdev, where, &u16val); | ||
1499 | len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, | ||
1500 | "%03x: %04x\n", where, u16val); | ||
1501 | break; | ||
1502 | case SIZE_U32: /* double word (32 bits) */ | ||
1503 | pci_read_config_dword(pdev, where, &u32val); | ||
1504 | len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, | ||
1505 | "%03x: %08x\n", where, u32val); | ||
1506 | break; | ||
1507 | case LPFC_PCI_CFG_SIZE: /* browse all */ | ||
1508 | goto pcicfg_browse; | ||
1509 | break; | ||
1510 | default: | ||
1511 | /* illegal count */ | ||
1512 | len = 0; | ||
1513 | break; | ||
1514 | } | ||
1515 | return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len); | ||
1516 | |||
1517 | pcicfg_browse: | ||
1518 | |||
1519 | /* Browse all PCI config space registers */ | ||
1520 | offset_label = idiag.offset.last_rd; | ||
1521 | offset = offset_label; | ||
1522 | |||
1523 | /* Read PCI config space */ | ||
1524 | len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, | ||
1525 | "%03x: ", offset_label); | ||
1526 | while (index > 0) { | ||
1527 | pci_read_config_dword(pdev, offset, &u32val); | ||
1528 | len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, | ||
1529 | "%08x ", u32val); | ||
1530 | offset += sizeof(uint32_t); | ||
1531 | index -= sizeof(uint32_t); | ||
1532 | if (!index) | ||
1533 | len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, | ||
1534 | "\n"); | ||
1535 | else if (!(index % (8 * sizeof(uint32_t)))) { | ||
1536 | offset_label += (8 * sizeof(uint32_t)); | ||
1537 | len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, | ||
1538 | "\n%03x: ", offset_label); | ||
1539 | } | ||
1540 | } | ||
1541 | |||
1542 | /* Set up the offset for next portion of pci cfg read */ | ||
1543 | idiag.offset.last_rd += LPFC_PCI_CFG_RD_SIZE; | ||
1544 | if (idiag.offset.last_rd >= LPFC_PCI_CFG_SIZE) | ||
1545 | idiag.offset.last_rd = 0; | ||
1546 | |||
1547 | return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len); | ||
1548 | } | ||
1549 | |||
1550 | /** | ||
1551 | * lpfc_idiag_pcicfg_write - Syntax check and set up idiag pcicfg commands | ||
1552 | * @file: The file pointer to read from. | ||
1553 | * @buf: The buffer to copy the user data from. | ||
1554 | * @nbytes: The number of bytes to get. | ||
1555 | * @ppos: The position in the file to start reading from. | ||
1556 | * | ||
1557 | * This routine get the debugfs idiag command struct from user space and | ||
1558 | * then perform the syntax check for PCI config space read or write command | ||
1559 | * accordingly. In the case of PCI config space read command, it sets up | ||
1560 | * the command in the idiag command struct for the debugfs read operation. | ||
1561 | * In the case of PCI config space write operation, it executes the write | ||
1562 | * operation into the PCI config space accordingly. | ||
1563 | * | ||
1564 | * It returns the @nbytges passing in from debugfs user space when successful. | ||
1565 | * In case of error conditions, it returns proper error code back to the user | ||
1566 | * space. | ||
1567 | */ | ||
1568 | static ssize_t | ||
1569 | lpfc_idiag_pcicfg_write(struct file *file, const char __user *buf, | ||
1570 | size_t nbytes, loff_t *ppos) | ||
1571 | { | ||
1572 | struct lpfc_debug *debug = file->private_data; | ||
1573 | struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private; | ||
1574 | uint32_t where, value, count; | ||
1575 | uint32_t u32val; | ||
1576 | uint16_t u16val; | ||
1577 | uint8_t u8val; | ||
1578 | struct pci_dev *pdev; | ||
1579 | int rc; | ||
1580 | |||
1581 | pdev = phba->pcidev; | ||
1582 | if (!pdev) | ||
1583 | return -EFAULT; | ||
1584 | |||
1585 | /* This is a user write operation */ | ||
1586 | debug->op = LPFC_IDIAG_OP_WR; | ||
1587 | |||
1588 | rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd); | ||
1589 | if (rc) | ||
1590 | return rc; | ||
1591 | |||
1592 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_RD) { | ||
1593 | /* Read command from PCI config space, set up command fields */ | ||
1594 | where = idiag.cmd.data[0]; | ||
1595 | count = idiag.cmd.data[1]; | ||
1596 | if (count == LPFC_PCI_CFG_SIZE) { | ||
1597 | if (where != 0) | ||
1598 | goto error_out; | ||
1599 | } else if ((count != sizeof(uint8_t)) && | ||
1600 | (count != sizeof(uint16_t)) && | ||
1601 | (count != sizeof(uint32_t))) | ||
1602 | goto error_out; | ||
1603 | if (count == sizeof(uint8_t)) { | ||
1604 | if (where > LPFC_PCI_CFG_SIZE - sizeof(uint8_t)) | ||
1605 | goto error_out; | ||
1606 | if (where % sizeof(uint8_t)) | ||
1607 | goto error_out; | ||
1608 | } | ||
1609 | if (count == sizeof(uint16_t)) { | ||
1610 | if (where > LPFC_PCI_CFG_SIZE - sizeof(uint16_t)) | ||
1611 | goto error_out; | ||
1612 | if (where % sizeof(uint16_t)) | ||
1613 | goto error_out; | ||
1614 | } | ||
1615 | if (count == sizeof(uint32_t)) { | ||
1616 | if (where > LPFC_PCI_CFG_SIZE - sizeof(uint32_t)) | ||
1617 | goto error_out; | ||
1618 | if (where % sizeof(uint32_t)) | ||
1619 | goto error_out; | ||
1620 | } | ||
1621 | } else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR || | ||
1622 | idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST || | ||
1623 | idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) { | ||
1624 | /* Write command to PCI config space, read-modify-write */ | ||
1625 | where = idiag.cmd.data[0]; | ||
1626 | count = idiag.cmd.data[1]; | ||
1627 | value = idiag.cmd.data[2]; | ||
1628 | /* Sanity checks */ | ||
1629 | if ((count != sizeof(uint8_t)) && | ||
1630 | (count != sizeof(uint16_t)) && | ||
1631 | (count != sizeof(uint32_t))) | ||
1632 | goto error_out; | ||
1633 | if (count == sizeof(uint8_t)) { | ||
1634 | if (where > LPFC_PCI_CFG_SIZE - sizeof(uint8_t)) | ||
1635 | goto error_out; | ||
1636 | if (where % sizeof(uint8_t)) | ||
1637 | goto error_out; | ||
1638 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR) | ||
1639 | pci_write_config_byte(pdev, where, | ||
1640 | (uint8_t)value); | ||
1641 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST) { | ||
1642 | rc = pci_read_config_byte(pdev, where, &u8val); | ||
1643 | if (!rc) { | ||
1644 | u8val |= (uint8_t)value; | ||
1645 | pci_write_config_byte(pdev, where, | ||
1646 | u8val); | ||
1647 | } | ||
1648 | } | ||
1649 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) { | ||
1650 | rc = pci_read_config_byte(pdev, where, &u8val); | ||
1651 | if (!rc) { | ||
1652 | u8val &= (uint8_t)(~value); | ||
1653 | pci_write_config_byte(pdev, where, | ||
1654 | u8val); | ||
1655 | } | ||
1656 | } | ||
1657 | } | ||
1658 | if (count == sizeof(uint16_t)) { | ||
1659 | if (where > LPFC_PCI_CFG_SIZE - sizeof(uint16_t)) | ||
1660 | goto error_out; | ||
1661 | if (where % sizeof(uint16_t)) | ||
1662 | goto error_out; | ||
1663 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR) | ||
1664 | pci_write_config_word(pdev, where, | ||
1665 | (uint16_t)value); | ||
1666 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST) { | ||
1667 | rc = pci_read_config_word(pdev, where, &u16val); | ||
1668 | if (!rc) { | ||
1669 | u16val |= (uint16_t)value; | ||
1670 | pci_write_config_word(pdev, where, | ||
1671 | u16val); | ||
1672 | } | ||
1673 | } | ||
1674 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) { | ||
1675 | rc = pci_read_config_word(pdev, where, &u16val); | ||
1676 | if (!rc) { | ||
1677 | u16val &= (uint16_t)(~value); | ||
1678 | pci_write_config_word(pdev, where, | ||
1679 | u16val); | ||
1680 | } | ||
1681 | } | ||
1682 | } | ||
1683 | if (count == sizeof(uint32_t)) { | ||
1684 | if (where > LPFC_PCI_CFG_SIZE - sizeof(uint32_t)) | ||
1685 | goto error_out; | ||
1686 | if (where % sizeof(uint32_t)) | ||
1687 | goto error_out; | ||
1688 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR) | ||
1689 | pci_write_config_dword(pdev, where, value); | ||
1690 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST) { | ||
1691 | rc = pci_read_config_dword(pdev, where, | ||
1692 | &u32val); | ||
1693 | if (!rc) { | ||
1694 | u32val |= value; | ||
1695 | pci_write_config_dword(pdev, where, | ||
1696 | u32val); | ||
1697 | } | ||
1698 | } | ||
1699 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) { | ||
1700 | rc = pci_read_config_dword(pdev, where, | ||
1701 | &u32val); | ||
1702 | if (!rc) { | ||
1703 | u32val &= ~value; | ||
1704 | pci_write_config_dword(pdev, where, | ||
1705 | u32val); | ||
1706 | } | ||
1707 | } | ||
1708 | } | ||
1709 | } else | ||
1710 | /* All other opecodes are illegal for now */ | ||
1711 | goto error_out; | ||
1712 | |||
1713 | return nbytes; | ||
1714 | error_out: | ||
1715 | memset(&idiag, 0, sizeof(idiag)); | ||
1716 | return -EINVAL; | ||
1717 | } | ||
1718 | |||
1719 | /** | ||
1720 | * lpfc_idiag_queinfo_read - idiag debugfs read queue information | ||
1721 | * @file: The file pointer to read from. | ||
1722 | * @buf: The buffer to copy the data to. | ||
1723 | * @nbytes: The number of bytes to read. | ||
1724 | * @ppos: The position in the file to start reading from. | ||
1725 | * | ||
1726 | * Description: | ||
1727 | * This routine reads data from the @phba SLI4 PCI function queue information, | ||
1728 | * and copies to user @buf. | ||
1729 | * | ||
1730 | * Returns: | ||
1731 | * This function returns the amount of data that was read (this could be less | ||
1732 | * than @nbytes if the end of the file was reached) or a negative error value. | ||
1733 | **/ | ||
1734 | static ssize_t | ||
1735 | lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes, | ||
1736 | loff_t *ppos) | ||
1737 | { | ||
1738 | struct lpfc_debug *debug = file->private_data; | ||
1739 | struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private; | ||
1740 | int len = 0, fcp_qidx; | ||
1741 | char *pbuffer; | ||
1742 | |||
1743 | if (!debug->buffer) | ||
1744 | debug->buffer = kmalloc(LPFC_QUE_INFO_GET_BUF_SIZE, GFP_KERNEL); | ||
1745 | if (!debug->buffer) | ||
1746 | return 0; | ||
1747 | pbuffer = debug->buffer; | ||
1748 | |||
1749 | if (*ppos) | ||
1750 | return 0; | ||
1751 | |||
1752 | /* Get slow-path event queue information */ | ||
1753 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1754 | "Slow-path EQ information:\n"); | ||
1755 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1756 | "\tID [%02d], EQE-COUNT [%04d], " | ||
1757 | "HOST-INDEX [%04x], PORT-INDEX [%04x]\n\n", | ||
1758 | phba->sli4_hba.sp_eq->queue_id, | ||
1759 | phba->sli4_hba.sp_eq->entry_count, | ||
1760 | phba->sli4_hba.sp_eq->host_index, | ||
1761 | phba->sli4_hba.sp_eq->hba_index); | ||
1762 | |||
1763 | /* Get fast-path event queue information */ | ||
1764 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1765 | "Fast-path EQ information:\n"); | ||
1766 | for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count; fcp_qidx++) { | ||
1767 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1768 | "\tID [%02d], EQE-COUNT [%04d], " | ||
1769 | "HOST-INDEX [%04x], PORT-INDEX [%04x]\n", | ||
1770 | phba->sli4_hba.fp_eq[fcp_qidx]->queue_id, | ||
1771 | phba->sli4_hba.fp_eq[fcp_qidx]->entry_count, | ||
1772 | phba->sli4_hba.fp_eq[fcp_qidx]->host_index, | ||
1773 | phba->sli4_hba.fp_eq[fcp_qidx]->hba_index); | ||
1774 | } | ||
1775 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "\n"); | ||
1776 | |||
1777 | /* Get mailbox complete queue information */ | ||
1778 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1779 | "Mailbox CQ information:\n"); | ||
1780 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1781 | "\t\tAssociated EQ-ID [%02d]:\n", | ||
1782 | phba->sli4_hba.mbx_cq->assoc_qid); | ||
1783 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1784 | "\tID [%02d], CQE-COUNT [%04d], " | ||
1785 | "HOST-INDEX [%04x], PORT-INDEX [%04x]\n\n", | ||
1786 | phba->sli4_hba.mbx_cq->queue_id, | ||
1787 | phba->sli4_hba.mbx_cq->entry_count, | ||
1788 | phba->sli4_hba.mbx_cq->host_index, | ||
1789 | phba->sli4_hba.mbx_cq->hba_index); | ||
1790 | |||
1791 | /* Get slow-path complete queue information */ | ||
1792 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1793 | "Slow-path CQ information:\n"); | ||
1794 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1795 | "\t\tAssociated EQ-ID [%02d]:\n", | ||
1796 | phba->sli4_hba.els_cq->assoc_qid); | ||
1797 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1798 | "\tID [%02d], CQE-COUNT [%04d], " | ||
1799 | "HOST-INDEX [%04x], PORT-INDEX [%04x]\n\n", | ||
1800 | phba->sli4_hba.els_cq->queue_id, | ||
1801 | phba->sli4_hba.els_cq->entry_count, | ||
1802 | phba->sli4_hba.els_cq->host_index, | ||
1803 | phba->sli4_hba.els_cq->hba_index); | ||
1804 | |||
1805 | /* Get fast-path complete queue information */ | ||
1806 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1807 | "Fast-path CQ information:\n"); | ||
1808 | for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count; fcp_qidx++) { | ||
1809 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1810 | "\t\tAssociated EQ-ID [%02d]:\n", | ||
1811 | phba->sli4_hba.fcp_cq[fcp_qidx]->assoc_qid); | ||
1812 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1813 | "\tID [%02d], EQE-COUNT [%04d], " | ||
1814 | "HOST-INDEX [%04x], PORT-INDEX [%04x]\n", | ||
1815 | phba->sli4_hba.fcp_cq[fcp_qidx]->queue_id, | ||
1816 | phba->sli4_hba.fcp_cq[fcp_qidx]->entry_count, | ||
1817 | phba->sli4_hba.fcp_cq[fcp_qidx]->host_index, | ||
1818 | phba->sli4_hba.fcp_cq[fcp_qidx]->hba_index); | ||
1819 | } | ||
1820 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "\n"); | ||
1821 | |||
1822 | /* Get mailbox queue information */ | ||
1823 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1824 | "Mailbox MQ information:\n"); | ||
1825 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1826 | "\t\tAssociated CQ-ID [%02d]:\n", | ||
1827 | phba->sli4_hba.mbx_wq->assoc_qid); | ||
1828 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1829 | "\tID [%02d], MQE-COUNT [%04d], " | ||
1830 | "HOST-INDEX [%04x], PORT-INDEX [%04x]\n\n", | ||
1831 | phba->sli4_hba.mbx_wq->queue_id, | ||
1832 | phba->sli4_hba.mbx_wq->entry_count, | ||
1833 | phba->sli4_hba.mbx_wq->host_index, | ||
1834 | phba->sli4_hba.mbx_wq->hba_index); | ||
1835 | |||
1836 | /* Get slow-path work queue information */ | ||
1837 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1838 | "Slow-path WQ information:\n"); | ||
1839 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1840 | "\t\tAssociated CQ-ID [%02d]:\n", | ||
1841 | phba->sli4_hba.els_wq->assoc_qid); | ||
1842 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1843 | "\tID [%02d], WQE-COUNT [%04d], " | ||
1844 | "HOST-INDEX [%04x], PORT-INDEX [%04x]\n\n", | ||
1845 | phba->sli4_hba.els_wq->queue_id, | ||
1846 | phba->sli4_hba.els_wq->entry_count, | ||
1847 | phba->sli4_hba.els_wq->host_index, | ||
1848 | phba->sli4_hba.els_wq->hba_index); | ||
1849 | |||
1850 | /* Get fast-path work queue information */ | ||
1851 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1852 | "Fast-path WQ information:\n"); | ||
1853 | for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_wq_count; fcp_qidx++) { | ||
1854 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1855 | "\t\tAssociated CQ-ID [%02d]:\n", | ||
1856 | phba->sli4_hba.fcp_wq[fcp_qidx]->assoc_qid); | ||
1857 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1858 | "\tID [%02d], WQE-COUNT [%04d], " | ||
1859 | "HOST-INDEX [%04x], PORT-INDEX [%04x]\n", | ||
1860 | phba->sli4_hba.fcp_wq[fcp_qidx]->queue_id, | ||
1861 | phba->sli4_hba.fcp_wq[fcp_qidx]->entry_count, | ||
1862 | phba->sli4_hba.fcp_wq[fcp_qidx]->host_index, | ||
1863 | phba->sli4_hba.fcp_wq[fcp_qidx]->hba_index); | ||
1864 | } | ||
1865 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "\n"); | ||
1866 | |||
1867 | /* Get receive queue information */ | ||
1868 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1869 | "Slow-path RQ information:\n"); | ||
1870 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1871 | "\t\tAssociated CQ-ID [%02d]:\n", | ||
1872 | phba->sli4_hba.hdr_rq->assoc_qid); | ||
1873 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1874 | "\tID [%02d], RHQE-COUNT [%04d], " | ||
1875 | "HOST-INDEX [%04x], PORT-INDEX [%04x]\n", | ||
1876 | phba->sli4_hba.hdr_rq->queue_id, | ||
1877 | phba->sli4_hba.hdr_rq->entry_count, | ||
1878 | phba->sli4_hba.hdr_rq->host_index, | ||
1879 | phba->sli4_hba.hdr_rq->hba_index); | ||
1880 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1881 | "\tID [%02d], RDQE-COUNT [%04d], " | ||
1882 | "HOST-INDEX [%04x], PORT-INDEX [%04x]\n", | ||
1883 | phba->sli4_hba.dat_rq->queue_id, | ||
1884 | phba->sli4_hba.dat_rq->entry_count, | ||
1885 | phba->sli4_hba.dat_rq->host_index, | ||
1886 | phba->sli4_hba.dat_rq->hba_index); | ||
1887 | |||
1888 | return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len); | ||
1889 | } | ||
1890 | |||
1140 | #undef lpfc_debugfs_op_disc_trc | 1891 | #undef lpfc_debugfs_op_disc_trc |
1141 | static const struct file_operations lpfc_debugfs_op_disc_trc = { | 1892 | static const struct file_operations lpfc_debugfs_op_disc_trc = { |
1142 | .owner = THIS_MODULE, | 1893 | .owner = THIS_MODULE, |
@@ -1213,6 +1964,28 @@ static const struct file_operations lpfc_debugfs_op_slow_ring_trc = { | |||
1213 | 1964 | ||
1214 | static struct dentry *lpfc_debugfs_root = NULL; | 1965 | static struct dentry *lpfc_debugfs_root = NULL; |
1215 | static atomic_t lpfc_debugfs_hba_count; | 1966 | static atomic_t lpfc_debugfs_hba_count; |
1967 | |||
1968 | /* | ||
1969 | * File operations for the iDiag debugfs | ||
1970 | */ | ||
1971 | #undef lpfc_idiag_op_pciCfg | ||
1972 | static const struct file_operations lpfc_idiag_op_pciCfg = { | ||
1973 | .owner = THIS_MODULE, | ||
1974 | .open = lpfc_idiag_open, | ||
1975 | .llseek = lpfc_debugfs_lseek, | ||
1976 | .read = lpfc_idiag_pcicfg_read, | ||
1977 | .write = lpfc_idiag_pcicfg_write, | ||
1978 | .release = lpfc_idiag_cmd_release, | ||
1979 | }; | ||
1980 | |||
1981 | #undef lpfc_idiag_op_queInfo | ||
1982 | static const struct file_operations lpfc_idiag_op_queInfo = { | ||
1983 | .owner = THIS_MODULE, | ||
1984 | .open = lpfc_idiag_open, | ||
1985 | .read = lpfc_idiag_queinfo_read, | ||
1986 | .release = lpfc_idiag_release, | ||
1987 | }; | ||
1988 | |||
1216 | #endif | 1989 | #endif |
1217 | 1990 | ||
1218 | /** | 1991 | /** |
@@ -1249,8 +2022,8 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport) | |||
1249 | if (!lpfc_debugfs_start_time) | 2022 | if (!lpfc_debugfs_start_time) |
1250 | lpfc_debugfs_start_time = jiffies; | 2023 | lpfc_debugfs_start_time = jiffies; |
1251 | 2024 | ||
1252 | /* Setup lpfcX directory for specific HBA */ | 2025 | /* Setup funcX directory for specific HBA PCI function */ |
1253 | snprintf(name, sizeof(name), "lpfc%d", phba->brd_no); | 2026 | snprintf(name, sizeof(name), "fn%d", phba->brd_no); |
1254 | if (!phba->hba_debugfs_root) { | 2027 | if (!phba->hba_debugfs_root) { |
1255 | phba->hba_debugfs_root = | 2028 | phba->hba_debugfs_root = |
1256 | debugfs_create_dir(name, lpfc_debugfs_root); | 2029 | debugfs_create_dir(name, lpfc_debugfs_root); |
@@ -1275,28 +2048,38 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport) | |||
1275 | } | 2048 | } |
1276 | 2049 | ||
1277 | /* Setup dumpHBASlim */ | 2050 | /* Setup dumpHBASlim */ |
1278 | snprintf(name, sizeof(name), "dumpHBASlim"); | 2051 | if (phba->sli_rev < LPFC_SLI_REV4) { |
1279 | phba->debug_dumpHBASlim = | 2052 | snprintf(name, sizeof(name), "dumpHBASlim"); |
1280 | debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, | 2053 | phba->debug_dumpHBASlim = |
1281 | phba->hba_debugfs_root, | 2054 | debugfs_create_file(name, |
1282 | phba, &lpfc_debugfs_op_dumpHBASlim); | 2055 | S_IFREG|S_IRUGO|S_IWUSR, |
1283 | if (!phba->debug_dumpHBASlim) { | 2056 | phba->hba_debugfs_root, |
1284 | lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, | 2057 | phba, &lpfc_debugfs_op_dumpHBASlim); |
1285 | "0413 Cannot create debugfs dumpHBASlim\n"); | 2058 | if (!phba->debug_dumpHBASlim) { |
1286 | goto debug_failed; | 2059 | lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, |
1287 | } | 2060 | "0413 Cannot create debugfs " |
2061 | "dumpHBASlim\n"); | ||
2062 | goto debug_failed; | ||
2063 | } | ||
2064 | } else | ||
2065 | phba->debug_dumpHBASlim = NULL; | ||
1288 | 2066 | ||
1289 | /* Setup dumpHostSlim */ | 2067 | /* Setup dumpHostSlim */ |
1290 | snprintf(name, sizeof(name), "dumpHostSlim"); | 2068 | if (phba->sli_rev < LPFC_SLI_REV4) { |
1291 | phba->debug_dumpHostSlim = | 2069 | snprintf(name, sizeof(name), "dumpHostSlim"); |
1292 | debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, | 2070 | phba->debug_dumpHostSlim = |
1293 | phba->hba_debugfs_root, | 2071 | debugfs_create_file(name, |
1294 | phba, &lpfc_debugfs_op_dumpHostSlim); | 2072 | S_IFREG|S_IRUGO|S_IWUSR, |
1295 | if (!phba->debug_dumpHostSlim) { | 2073 | phba->hba_debugfs_root, |
1296 | lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, | 2074 | phba, &lpfc_debugfs_op_dumpHostSlim); |
1297 | "0414 Cannot create debugfs dumpHostSlim\n"); | 2075 | if (!phba->debug_dumpHostSlim) { |
1298 | goto debug_failed; | 2076 | lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, |
1299 | } | 2077 | "0414 Cannot create debugfs " |
2078 | "dumpHostSlim\n"); | ||
2079 | goto debug_failed; | ||
2080 | } | ||
2081 | } else | ||
2082 | phba->debug_dumpHBASlim = NULL; | ||
1300 | 2083 | ||
1301 | /* Setup dumpData */ | 2084 | /* Setup dumpData */ |
1302 | snprintf(name, sizeof(name), "dumpData"); | 2085 | snprintf(name, sizeof(name), "dumpData"); |
@@ -1322,8 +2105,6 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport) | |||
1322 | goto debug_failed; | 2105 | goto debug_failed; |
1323 | } | 2106 | } |
1324 | 2107 | ||
1325 | |||
1326 | |||
1327 | /* Setup slow ring trace */ | 2108 | /* Setup slow ring trace */ |
1328 | if (lpfc_debugfs_max_slow_ring_trc) { | 2109 | if (lpfc_debugfs_max_slow_ring_trc) { |
1329 | num = lpfc_debugfs_max_slow_ring_trc - 1; | 2110 | num = lpfc_debugfs_max_slow_ring_trc - 1; |
@@ -1342,7 +2123,6 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport) | |||
1342 | } | 2123 | } |
1343 | } | 2124 | } |
1344 | 2125 | ||
1345 | |||
1346 | snprintf(name, sizeof(name), "slow_ring_trace"); | 2126 | snprintf(name, sizeof(name), "slow_ring_trace"); |
1347 | phba->debug_slow_ring_trc = | 2127 | phba->debug_slow_ring_trc = |
1348 | debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, | 2128 | debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, |
@@ -1434,6 +2214,53 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport) | |||
1434 | "0409 Cant create debugfs nodelist\n"); | 2214 | "0409 Cant create debugfs nodelist\n"); |
1435 | goto debug_failed; | 2215 | goto debug_failed; |
1436 | } | 2216 | } |
2217 | |||
2218 | /* | ||
2219 | * iDiag debugfs root entry points for SLI4 device only | ||
2220 | */ | ||
2221 | if (phba->sli_rev < LPFC_SLI_REV4) | ||
2222 | goto debug_failed; | ||
2223 | |||
2224 | snprintf(name, sizeof(name), "iDiag"); | ||
2225 | if (!phba->idiag_root) { | ||
2226 | phba->idiag_root = | ||
2227 | debugfs_create_dir(name, phba->hba_debugfs_root); | ||
2228 | if (!phba->idiag_root) { | ||
2229 | lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, | ||
2230 | "2922 Can't create idiag debugfs\n"); | ||
2231 | goto debug_failed; | ||
2232 | } | ||
2233 | /* Initialize iDiag data structure */ | ||
2234 | memset(&idiag, 0, sizeof(idiag)); | ||
2235 | } | ||
2236 | |||
2237 | /* iDiag read PCI config space */ | ||
2238 | snprintf(name, sizeof(name), "pciCfg"); | ||
2239 | if (!phba->idiag_pci_cfg) { | ||
2240 | phba->idiag_pci_cfg = | ||
2241 | debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, | ||
2242 | phba->idiag_root, phba, &lpfc_idiag_op_pciCfg); | ||
2243 | if (!phba->idiag_pci_cfg) { | ||
2244 | lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, | ||
2245 | "2923 Can't create idiag debugfs\n"); | ||
2246 | goto debug_failed; | ||
2247 | } | ||
2248 | idiag.offset.last_rd = 0; | ||
2249 | } | ||
2250 | |||
2251 | /* iDiag get PCI function queue information */ | ||
2252 | snprintf(name, sizeof(name), "queInfo"); | ||
2253 | if (!phba->idiag_que_info) { | ||
2254 | phba->idiag_que_info = | ||
2255 | debugfs_create_file(name, S_IFREG|S_IRUGO, | ||
2256 | phba->idiag_root, phba, &lpfc_idiag_op_queInfo); | ||
2257 | if (!phba->idiag_que_info) { | ||
2258 | lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, | ||
2259 | "2924 Can't create idiag debugfs\n"); | ||
2260 | goto debug_failed; | ||
2261 | } | ||
2262 | } | ||
2263 | |||
1437 | debug_failed: | 2264 | debug_failed: |
1438 | return; | 2265 | return; |
1439 | #endif | 2266 | #endif |
@@ -1508,8 +2335,31 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport) | |||
1508 | phba->debug_slow_ring_trc = NULL; | 2335 | phba->debug_slow_ring_trc = NULL; |
1509 | } | 2336 | } |
1510 | 2337 | ||
2338 | /* | ||
2339 | * iDiag release | ||
2340 | */ | ||
2341 | if (phba->sli_rev == LPFC_SLI_REV4) { | ||
2342 | if (phba->idiag_que_info) { | ||
2343 | /* iDiag queInfo */ | ||
2344 | debugfs_remove(phba->idiag_que_info); | ||
2345 | phba->idiag_que_info = NULL; | ||
2346 | } | ||
2347 | if (phba->idiag_pci_cfg) { | ||
2348 | /* iDiag pciCfg */ | ||
2349 | debugfs_remove(phba->idiag_pci_cfg); | ||
2350 | phba->idiag_pci_cfg = NULL; | ||
2351 | } | ||
2352 | |||
2353 | /* Finally remove the iDiag debugfs root */ | ||
2354 | if (phba->idiag_root) { | ||
2355 | /* iDiag root */ | ||
2356 | debugfs_remove(phba->idiag_root); | ||
2357 | phba->idiag_root = NULL; | ||
2358 | } | ||
2359 | } | ||
2360 | |||
1511 | if (phba->hba_debugfs_root) { | 2361 | if (phba->hba_debugfs_root) { |
1512 | debugfs_remove(phba->hba_debugfs_root); /* lpfcX */ | 2362 | debugfs_remove(phba->hba_debugfs_root); /* fnX */ |
1513 | phba->hba_debugfs_root = NULL; | 2363 | phba->hba_debugfs_root = NULL; |
1514 | atomic_dec(&lpfc_debugfs_hba_count); | 2364 | atomic_dec(&lpfc_debugfs_hba_count); |
1515 | } | 2365 | } |
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.h b/drivers/scsi/lpfc/lpfc_debugfs.h index 03c7313a1012..91b9a9427cda 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.h +++ b/drivers/scsi/lpfc/lpfc_debugfs.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2007 Emulex. All rights reserved. * | 4 | * Copyright (C) 2007-2011 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * * | 7 | * * |
@@ -22,6 +22,44 @@ | |||
22 | #define _H_LPFC_DEBUG_FS | 22 | #define _H_LPFC_DEBUG_FS |
23 | 23 | ||
24 | #ifdef CONFIG_SCSI_LPFC_DEBUG_FS | 24 | #ifdef CONFIG_SCSI_LPFC_DEBUG_FS |
25 | |||
26 | /* size of output line, for discovery_trace and slow_ring_trace */ | ||
27 | #define LPFC_DEBUG_TRC_ENTRY_SIZE 100 | ||
28 | |||
29 | /* nodelist output buffer size */ | ||
30 | #define LPFC_NODELIST_SIZE 8192 | ||
31 | #define LPFC_NODELIST_ENTRY_SIZE 120 | ||
32 | |||
33 | /* dumpHBASlim output buffer size */ | ||
34 | #define LPFC_DUMPHBASLIM_SIZE 4096 | ||
35 | |||
36 | /* dumpHostSlim output buffer size */ | ||
37 | #define LPFC_DUMPHOSTSLIM_SIZE 4096 | ||
38 | |||
39 | /* hbqinfo output buffer size */ | ||
40 | #define LPFC_HBQINFO_SIZE 8192 | ||
41 | |||
42 | /* rdPciConf output buffer size */ | ||
43 | #define LPFC_PCI_CFG_SIZE 4096 | ||
44 | #define LPFC_PCI_CFG_RD_BUF_SIZE (LPFC_PCI_CFG_SIZE/2) | ||
45 | #define LPFC_PCI_CFG_RD_SIZE (LPFC_PCI_CFG_SIZE/4) | ||
46 | |||
47 | /* queue info output buffer size */ | ||
48 | #define LPFC_QUE_INFO_GET_BUF_SIZE 2048 | ||
49 | |||
50 | #define SIZE_U8 sizeof(uint8_t) | ||
51 | #define SIZE_U16 sizeof(uint16_t) | ||
52 | #define SIZE_U32 sizeof(uint32_t) | ||
53 | |||
54 | struct lpfc_debug { | ||
55 | char *i_private; | ||
56 | char op; | ||
57 | #define LPFC_IDIAG_OP_RD 1 | ||
58 | #define LPFC_IDIAG_OP_WR 2 | ||
59 | char *buffer; | ||
60 | int len; | ||
61 | }; | ||
62 | |||
25 | struct lpfc_debugfs_trc { | 63 | struct lpfc_debugfs_trc { |
26 | char *fmt; | 64 | char *fmt; |
27 | uint32_t data1; | 65 | uint32_t data1; |
@@ -30,6 +68,26 @@ struct lpfc_debugfs_trc { | |||
30 | uint32_t seq_cnt; | 68 | uint32_t seq_cnt; |
31 | unsigned long jif; | 69 | unsigned long jif; |
32 | }; | 70 | }; |
71 | |||
72 | struct lpfc_idiag_offset { | ||
73 | uint32_t last_rd; | ||
74 | }; | ||
75 | |||
76 | #define LPFC_IDIAG_CMD_DATA_SIZE 4 | ||
77 | struct lpfc_idiag_cmd { | ||
78 | uint32_t opcode; | ||
79 | #define LPFC_IDIAG_CMD_PCICFG_RD 0x00000001 | ||
80 | #define LPFC_IDIAG_CMD_PCICFG_WR 0x00000002 | ||
81 | #define LPFC_IDIAG_CMD_PCICFG_ST 0x00000003 | ||
82 | #define LPFC_IDIAG_CMD_PCICFG_CL 0x00000004 | ||
83 | uint32_t data[LPFC_IDIAG_CMD_DATA_SIZE]; | ||
84 | }; | ||
85 | |||
86 | struct lpfc_idiag { | ||
87 | uint32_t active; | ||
88 | struct lpfc_idiag_cmd cmd; | ||
89 | struct lpfc_idiag_offset offset; | ||
90 | }; | ||
33 | #endif | 91 | #endif |
34 | 92 | ||
35 | /* Mask for discovery_trace */ | 93 | /* Mask for discovery_trace */ |
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index c62d567cc845..8e28edf9801e 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2004-2009 Emulex. All rights reserved. * | 4 | * Copyright (C) 2004-2011 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * | 7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * |
@@ -485,6 +485,59 @@ fail: | |||
485 | } | 485 | } |
486 | 486 | ||
487 | /** | 487 | /** |
488 | * lpfc_check_clean_addr_bit - Check whether assigned FCID is clean. | ||
489 | * @vport: pointer to a host virtual N_Port data structure. | ||
490 | * @sp: pointer to service parameter data structure. | ||
491 | * | ||
492 | * This routine is called from FLOGI/FDISC completion handler functions. | ||
493 | * lpfc_check_clean_addr_bit return 1 when FCID/Fabric portname/ Fabric | ||
494 | * node nodename is changed in the completion service parameter else return | ||
495 | * 0. This function also set flag in the vport data structure to delay | ||
496 | * NP_Port discovery after the FLOGI/FDISC completion if Clean address bit | ||
497 | * in FLOGI/FDISC response is cleared and FCID/Fabric portname/ Fabric | ||
498 | * node nodename is changed in the completion service parameter. | ||
499 | * | ||
500 | * Return code | ||
501 | * 0 - FCID and Fabric Nodename and Fabric portname is not changed. | ||
502 | * 1 - FCID or Fabric Nodename or Fabric portname is changed. | ||
503 | * | ||
504 | **/ | ||
505 | static uint8_t | ||
506 | lpfc_check_clean_addr_bit(struct lpfc_vport *vport, | ||
507 | struct serv_parm *sp) | ||
508 | { | ||
509 | uint8_t fabric_param_changed = 0; | ||
510 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
511 | |||
512 | if ((vport->fc_prevDID != vport->fc_myDID) || | ||
513 | memcmp(&vport->fabric_portname, &sp->portName, | ||
514 | sizeof(struct lpfc_name)) || | ||
515 | memcmp(&vport->fabric_nodename, &sp->nodeName, | ||
516 | sizeof(struct lpfc_name))) | ||
517 | fabric_param_changed = 1; | ||
518 | |||
519 | /* | ||
520 | * Word 1 Bit 31 in common service parameter is overloaded. | ||
521 | * Word 1 Bit 31 in FLOGI request is multiple NPort request | ||
522 | * Word 1 Bit 31 in FLOGI response is clean address bit | ||
523 | * | ||
524 | * If fabric parameter is changed and clean address bit is | ||
525 | * cleared delay nport discovery if | ||
526 | * - vport->fc_prevDID != 0 (not initial discovery) OR | ||
527 | * - lpfc_delay_discovery module parameter is set. | ||
528 | */ | ||
529 | if (fabric_param_changed && !sp->cmn.clean_address_bit && | ||
530 | (vport->fc_prevDID || lpfc_delay_discovery)) { | ||
531 | spin_lock_irq(shost->host_lock); | ||
532 | vport->fc_flag |= FC_DISC_DELAYED; | ||
533 | spin_unlock_irq(shost->host_lock); | ||
534 | } | ||
535 | |||
536 | return fabric_param_changed; | ||
537 | } | ||
538 | |||
539 | |||
540 | /** | ||
488 | * lpfc_cmpl_els_flogi_fabric - Completion function for flogi to a fabric port | 541 | * lpfc_cmpl_els_flogi_fabric - Completion function for flogi to a fabric port |
489 | * @vport: pointer to a host virtual N_Port data structure. | 542 | * @vport: pointer to a host virtual N_Port data structure. |
490 | * @ndlp: pointer to a node-list data structure. | 543 | * @ndlp: pointer to a node-list data structure. |
@@ -512,6 +565,7 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
512 | struct lpfc_hba *phba = vport->phba; | 565 | struct lpfc_hba *phba = vport->phba; |
513 | struct lpfc_nodelist *np; | 566 | struct lpfc_nodelist *np; |
514 | struct lpfc_nodelist *next_np; | 567 | struct lpfc_nodelist *next_np; |
568 | uint8_t fabric_param_changed; | ||
515 | 569 | ||
516 | spin_lock_irq(shost->host_lock); | 570 | spin_lock_irq(shost->host_lock); |
517 | vport->fc_flag |= FC_FABRIC; | 571 | vport->fc_flag |= FC_FABRIC; |
@@ -544,6 +598,12 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
544 | ndlp->nlp_class_sup |= FC_COS_CLASS4; | 598 | ndlp->nlp_class_sup |= FC_COS_CLASS4; |
545 | ndlp->nlp_maxframe = ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | | 599 | ndlp->nlp_maxframe = ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | |
546 | sp->cmn.bbRcvSizeLsb; | 600 | sp->cmn.bbRcvSizeLsb; |
601 | |||
602 | fabric_param_changed = lpfc_check_clean_addr_bit(vport, sp); | ||
603 | memcpy(&vport->fabric_portname, &sp->portName, | ||
604 | sizeof(struct lpfc_name)); | ||
605 | memcpy(&vport->fabric_nodename, &sp->nodeName, | ||
606 | sizeof(struct lpfc_name)); | ||
547 | memcpy(&phba->fc_fabparam, sp, sizeof(struct serv_parm)); | 607 | memcpy(&phba->fc_fabparam, sp, sizeof(struct serv_parm)); |
548 | 608 | ||
549 | if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) { | 609 | if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) { |
@@ -565,7 +625,7 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
565 | } | 625 | } |
566 | } | 626 | } |
567 | 627 | ||
568 | if ((vport->fc_prevDID != vport->fc_myDID) && | 628 | if (fabric_param_changed && |
569 | !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) { | 629 | !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) { |
570 | 630 | ||
571 | /* If our NportID changed, we need to ensure all | 631 | /* If our NportID changed, we need to ensure all |
@@ -2203,6 +2263,7 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
2203 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 2263 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
2204 | IOCB_t *irsp; | 2264 | IOCB_t *irsp; |
2205 | struct lpfc_sli *psli; | 2265 | struct lpfc_sli *psli; |
2266 | struct lpfcMboxq *mbox; | ||
2206 | 2267 | ||
2207 | psli = &phba->sli; | 2268 | psli = &phba->sli; |
2208 | /* we pass cmdiocb to state machine which needs rspiocb as well */ | 2269 | /* we pass cmdiocb to state machine which needs rspiocb as well */ |
@@ -2260,6 +2321,21 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
2260 | NLP_EVT_CMPL_LOGO); | 2321 | NLP_EVT_CMPL_LOGO); |
2261 | out: | 2322 | out: |
2262 | lpfc_els_free_iocb(phba, cmdiocb); | 2323 | lpfc_els_free_iocb(phba, cmdiocb); |
2324 | /* If we are in pt2pt mode, we could rcv new S_ID on PLOGI */ | ||
2325 | if ((vport->fc_flag & FC_PT2PT) && | ||
2326 | !(vport->fc_flag & FC_PT2PT_PLOGI)) { | ||
2327 | phba->pport->fc_myDID = 0; | ||
2328 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
2329 | if (mbox) { | ||
2330 | lpfc_config_link(phba, mbox); | ||
2331 | mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | ||
2332 | mbox->vport = vport; | ||
2333 | if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT) == | ||
2334 | MBX_NOT_FINISHED) { | ||
2335 | mempool_free(mbox, phba->mbox_mem_pool); | ||
2336 | } | ||
2337 | } | ||
2338 | } | ||
2263 | return; | 2339 | return; |
2264 | } | 2340 | } |
2265 | 2341 | ||
@@ -2745,7 +2821,8 @@ lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp) | |||
2745 | } | 2821 | } |
2746 | break; | 2822 | break; |
2747 | case ELS_CMD_FDISC: | 2823 | case ELS_CMD_FDISC: |
2748 | lpfc_issue_els_fdisc(vport, ndlp, retry); | 2824 | if (!(vport->fc_flag & FC_VPORT_NEEDS_INIT_VPI)) |
2825 | lpfc_issue_els_fdisc(vport, ndlp, retry); | ||
2749 | break; | 2826 | break; |
2750 | } | 2827 | } |
2751 | return; | 2828 | return; |
@@ -2815,9 +2892,17 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
2815 | 2892 | ||
2816 | switch (irsp->ulpStatus) { | 2893 | switch (irsp->ulpStatus) { |
2817 | case IOSTAT_FCP_RSP_ERROR: | 2894 | case IOSTAT_FCP_RSP_ERROR: |
2895 | break; | ||
2818 | case IOSTAT_REMOTE_STOP: | 2896 | case IOSTAT_REMOTE_STOP: |
2897 | if (phba->sli_rev == LPFC_SLI_REV4) { | ||
2898 | /* This IO was aborted by the target, we don't | ||
2899 | * know the rxid and because we did not send the | ||
2900 | * ABTS we cannot generate and RRQ. | ||
2901 | */ | ||
2902 | lpfc_set_rrq_active(phba, ndlp, | ||
2903 | cmdiocb->sli4_xritag, 0, 0); | ||
2904 | } | ||
2819 | break; | 2905 | break; |
2820 | |||
2821 | case IOSTAT_LOCAL_REJECT: | 2906 | case IOSTAT_LOCAL_REJECT: |
2822 | switch ((irsp->un.ulpWord[4] & 0xff)) { | 2907 | switch ((irsp->un.ulpWord[4] & 0xff)) { |
2823 | case IOERR_LOOP_OPEN_FAILURE: | 2908 | case IOERR_LOOP_OPEN_FAILURE: |
@@ -4013,28 +4098,34 @@ lpfc_els_clear_rrq(struct lpfc_vport *vport, | |||
4013 | uint8_t *pcmd; | 4098 | uint8_t *pcmd; |
4014 | struct RRQ *rrq; | 4099 | struct RRQ *rrq; |
4015 | uint16_t rxid; | 4100 | uint16_t rxid; |
4101 | uint16_t xri; | ||
4016 | struct lpfc_node_rrq *prrq; | 4102 | struct lpfc_node_rrq *prrq; |
4017 | 4103 | ||
4018 | 4104 | ||
4019 | pcmd = (uint8_t *) (((struct lpfc_dmabuf *) iocb->context2)->virt); | 4105 | pcmd = (uint8_t *) (((struct lpfc_dmabuf *) iocb->context2)->virt); |
4020 | pcmd += sizeof(uint32_t); | 4106 | pcmd += sizeof(uint32_t); |
4021 | rrq = (struct RRQ *)pcmd; | 4107 | rrq = (struct RRQ *)pcmd; |
4022 | rxid = bf_get(rrq_oxid, rrq); | 4108 | rrq->rrq_exchg = be32_to_cpu(rrq->rrq_exchg); |
4109 | rxid = be16_to_cpu(bf_get(rrq_rxid, rrq)); | ||
4023 | 4110 | ||
4024 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | 4111 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
4025 | "2883 Clear RRQ for SID:x%x OXID:x%x RXID:x%x" | 4112 | "2883 Clear RRQ for SID:x%x OXID:x%x RXID:x%x" |
4026 | " x%x x%x\n", | 4113 | " x%x x%x\n", |
4027 | bf_get(rrq_did, rrq), | 4114 | be32_to_cpu(bf_get(rrq_did, rrq)), |
4028 | bf_get(rrq_oxid, rrq), | 4115 | be16_to_cpu(bf_get(rrq_oxid, rrq)), |
4029 | rxid, | 4116 | rxid, |
4030 | iocb->iotag, iocb->iocb.ulpContext); | 4117 | iocb->iotag, iocb->iocb.ulpContext); |
4031 | 4118 | ||
4032 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, | 4119 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, |
4033 | "Clear RRQ: did:x%x flg:x%x exchg:x%.08x", | 4120 | "Clear RRQ: did:x%x flg:x%x exchg:x%.08x", |
4034 | ndlp->nlp_DID, ndlp->nlp_flag, rrq->rrq_exchg); | 4121 | ndlp->nlp_DID, ndlp->nlp_flag, rrq->rrq_exchg); |
4035 | prrq = lpfc_get_active_rrq(vport, rxid, ndlp->nlp_DID); | 4122 | if (vport->fc_myDID == be32_to_cpu(bf_get(rrq_did, rrq))) |
4123 | xri = be16_to_cpu(bf_get(rrq_oxid, rrq)); | ||
4124 | else | ||
4125 | xri = rxid; | ||
4126 | prrq = lpfc_get_active_rrq(vport, xri, ndlp->nlp_DID); | ||
4036 | if (prrq) | 4127 | if (prrq) |
4037 | lpfc_clr_rrq_active(phba, rxid, prrq); | 4128 | lpfc_clr_rrq_active(phba, xri, prrq); |
4038 | return; | 4129 | return; |
4039 | } | 4130 | } |
4040 | 4131 | ||
@@ -6166,6 +6257,11 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
6166 | if (vport->load_flag & FC_UNLOADING) | 6257 | if (vport->load_flag & FC_UNLOADING) |
6167 | goto dropit; | 6258 | goto dropit; |
6168 | 6259 | ||
6260 | /* If NPort discovery is delayed drop incoming ELS */ | ||
6261 | if ((vport->fc_flag & FC_DISC_DELAYED) && | ||
6262 | (cmd != ELS_CMD_PLOGI)) | ||
6263 | goto dropit; | ||
6264 | |||
6169 | ndlp = lpfc_findnode_did(vport, did); | 6265 | ndlp = lpfc_findnode_did(vport, did); |
6170 | if (!ndlp) { | 6266 | if (!ndlp) { |
6171 | /* Cannot find existing Fabric ndlp, so allocate a new one */ | 6267 | /* Cannot find existing Fabric ndlp, so allocate a new one */ |
@@ -6218,6 +6314,12 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
6218 | ndlp = lpfc_plogi_confirm_nport(phba, payload, ndlp); | 6314 | ndlp = lpfc_plogi_confirm_nport(phba, payload, ndlp); |
6219 | 6315 | ||
6220 | lpfc_send_els_event(vport, ndlp, payload); | 6316 | lpfc_send_els_event(vport, ndlp, payload); |
6317 | |||
6318 | /* If Nport discovery is delayed, reject PLOGIs */ | ||
6319 | if (vport->fc_flag & FC_DISC_DELAYED) { | ||
6320 | rjt_err = LSRJT_UNABLE_TPC; | ||
6321 | break; | ||
6322 | } | ||
6221 | if (vport->port_state < LPFC_DISC_AUTH) { | 6323 | if (vport->port_state < LPFC_DISC_AUTH) { |
6222 | if (!(phba->pport->fc_flag & FC_PT2PT) || | 6324 | if (!(phba->pport->fc_flag & FC_PT2PT) || |
6223 | (phba->pport->fc_flag & FC_PT2PT_PLOGI)) { | 6325 | (phba->pport->fc_flag & FC_PT2PT_PLOGI)) { |
@@ -6596,6 +6698,21 @@ void | |||
6596 | lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport) | 6698 | lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport) |
6597 | { | 6699 | { |
6598 | struct lpfc_nodelist *ndlp, *ndlp_fdmi; | 6700 | struct lpfc_nodelist *ndlp, *ndlp_fdmi; |
6701 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
6702 | |||
6703 | /* | ||
6704 | * If lpfc_delay_discovery parameter is set and the clean address | ||
6705 | * bit is cleared and fc fabric parameters chenged, delay FC NPort | ||
6706 | * discovery. | ||
6707 | */ | ||
6708 | spin_lock_irq(shost->host_lock); | ||
6709 | if (vport->fc_flag & FC_DISC_DELAYED) { | ||
6710 | spin_unlock_irq(shost->host_lock); | ||
6711 | mod_timer(&vport->delayed_disc_tmo, | ||
6712 | jiffies + HZ * phba->fc_ratov); | ||
6713 | return; | ||
6714 | } | ||
6715 | spin_unlock_irq(shost->host_lock); | ||
6599 | 6716 | ||
6600 | ndlp = lpfc_findnode_did(vport, NameServer_DID); | 6717 | ndlp = lpfc_findnode_did(vport, NameServer_DID); |
6601 | if (!ndlp) { | 6718 | if (!ndlp) { |
@@ -6938,6 +7055,9 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
6938 | struct lpfc_nodelist *next_np; | 7055 | struct lpfc_nodelist *next_np; |
6939 | IOCB_t *irsp = &rspiocb->iocb; | 7056 | IOCB_t *irsp = &rspiocb->iocb; |
6940 | struct lpfc_iocbq *piocb; | 7057 | struct lpfc_iocbq *piocb; |
7058 | struct lpfc_dmabuf *pcmd = cmdiocb->context2, *prsp; | ||
7059 | struct serv_parm *sp; | ||
7060 | uint8_t fabric_param_changed; | ||
6941 | 7061 | ||
6942 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | 7062 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
6943 | "0123 FDISC completes. x%x/x%x prevDID: x%x\n", | 7063 | "0123 FDISC completes. x%x/x%x prevDID: x%x\n", |
@@ -6981,7 +7101,14 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
6981 | 7101 | ||
6982 | vport->fc_myDID = irsp->un.ulpWord[4] & Mask_DID; | 7102 | vport->fc_myDID = irsp->un.ulpWord[4] & Mask_DID; |
6983 | lpfc_vport_set_state(vport, FC_VPORT_ACTIVE); | 7103 | lpfc_vport_set_state(vport, FC_VPORT_ACTIVE); |
6984 | if ((vport->fc_prevDID != vport->fc_myDID) && | 7104 | prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf, list); |
7105 | sp = prsp->virt + sizeof(uint32_t); | ||
7106 | fabric_param_changed = lpfc_check_clean_addr_bit(vport, sp); | ||
7107 | memcpy(&vport->fabric_portname, &sp->portName, | ||
7108 | sizeof(struct lpfc_name)); | ||
7109 | memcpy(&vport->fabric_nodename, &sp->nodeName, | ||
7110 | sizeof(struct lpfc_name)); | ||
7111 | if (fabric_param_changed && | ||
6985 | !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) { | 7112 | !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) { |
6986 | /* If our NportID changed, we need to ensure all | 7113 | /* If our NportID changed, we need to ensure all |
6987 | * remaining NPORTs get unreg_login'ed so we can | 7114 | * remaining NPORTs get unreg_login'ed so we can |
@@ -7582,6 +7709,32 @@ void lpfc_fabric_abort_hba(struct lpfc_hba *phba) | |||
7582 | } | 7709 | } |
7583 | 7710 | ||
7584 | /** | 7711 | /** |
7712 | * lpfc_sli4_vport_delete_els_xri_aborted -Remove all ndlp references for vport | ||
7713 | * @vport: pointer to lpfc vport data structure. | ||
7714 | * | ||
7715 | * This routine is invoked by the vport cleanup for deletions and the cleanup | ||
7716 | * for an ndlp on removal. | ||
7717 | **/ | ||
7718 | void | ||
7719 | lpfc_sli4_vport_delete_els_xri_aborted(struct lpfc_vport *vport) | ||
7720 | { | ||
7721 | struct lpfc_hba *phba = vport->phba; | ||
7722 | struct lpfc_sglq *sglq_entry = NULL, *sglq_next = NULL; | ||
7723 | unsigned long iflag = 0; | ||
7724 | |||
7725 | spin_lock_irqsave(&phba->hbalock, iflag); | ||
7726 | spin_lock(&phba->sli4_hba.abts_sgl_list_lock); | ||
7727 | list_for_each_entry_safe(sglq_entry, sglq_next, | ||
7728 | &phba->sli4_hba.lpfc_abts_els_sgl_list, list) { | ||
7729 | if (sglq_entry->ndlp && sglq_entry->ndlp->vport == vport) | ||
7730 | sglq_entry->ndlp = NULL; | ||
7731 | } | ||
7732 | spin_unlock(&phba->sli4_hba.abts_sgl_list_lock); | ||
7733 | spin_unlock_irqrestore(&phba->hbalock, iflag); | ||
7734 | return; | ||
7735 | } | ||
7736 | |||
7737 | /** | ||
7585 | * lpfc_sli4_els_xri_aborted - Slow-path process of els xri abort | 7738 | * lpfc_sli4_els_xri_aborted - Slow-path process of els xri abort |
7586 | * @phba: pointer to lpfc hba data structure. | 7739 | * @phba: pointer to lpfc hba data structure. |
7587 | * @axri: pointer to the els xri abort wcqe structure. | 7740 | * @axri: pointer to the els xri abort wcqe structure. |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index bb015960dbc9..154c715fb3af 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -658,6 +658,8 @@ lpfc_work_done(struct lpfc_hba *phba) | |||
658 | lpfc_ramp_down_queue_handler(phba); | 658 | lpfc_ramp_down_queue_handler(phba); |
659 | if (work_port_events & WORKER_RAMP_UP_QUEUE) | 659 | if (work_port_events & WORKER_RAMP_UP_QUEUE) |
660 | lpfc_ramp_up_queue_handler(phba); | 660 | lpfc_ramp_up_queue_handler(phba); |
661 | if (work_port_events & WORKER_DELAYED_DISC_TMO) | ||
662 | lpfc_delayed_disc_timeout_handler(vport); | ||
661 | } | 663 | } |
662 | lpfc_destroy_vport_work_array(phba, vports); | 664 | lpfc_destroy_vport_work_array(phba, vports); |
663 | 665 | ||
@@ -838,6 +840,11 @@ lpfc_linkdown_port(struct lpfc_vport *vport) | |||
838 | 840 | ||
839 | lpfc_port_link_failure(vport); | 841 | lpfc_port_link_failure(vport); |
840 | 842 | ||
843 | /* Stop delayed Nport discovery */ | ||
844 | spin_lock_irq(shost->host_lock); | ||
845 | vport->fc_flag &= ~FC_DISC_DELAYED; | ||
846 | spin_unlock_irq(shost->host_lock); | ||
847 | del_timer_sync(&vport->delayed_disc_tmo); | ||
841 | } | 848 | } |
842 | 849 | ||
843 | int | 850 | int |
@@ -3160,7 +3167,7 @@ lpfc_mbx_cmpl_unreg_vpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
3160 | spin_unlock_irq(shost->host_lock); | 3167 | spin_unlock_irq(shost->host_lock); |
3161 | vport->unreg_vpi_cmpl = VPORT_OK; | 3168 | vport->unreg_vpi_cmpl = VPORT_OK; |
3162 | mempool_free(pmb, phba->mbox_mem_pool); | 3169 | mempool_free(pmb, phba->mbox_mem_pool); |
3163 | lpfc_cleanup_vports_rrqs(vport); | 3170 | lpfc_cleanup_vports_rrqs(vport, NULL); |
3164 | /* | 3171 | /* |
3165 | * This shost reference might have been taken at the beginning of | 3172 | * This shost reference might have been taken at the beginning of |
3166 | * lpfc_vport_delete() | 3173 | * lpfc_vport_delete() |
@@ -3900,6 +3907,8 @@ lpfc_drop_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
3900 | if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) | 3907 | if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) |
3901 | return; | 3908 | return; |
3902 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); | 3909 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); |
3910 | if (vport->phba->sli_rev == LPFC_SLI_REV4) | ||
3911 | lpfc_cleanup_vports_rrqs(vport, ndlp); | ||
3903 | lpfc_nlp_put(ndlp); | 3912 | lpfc_nlp_put(ndlp); |
3904 | return; | 3913 | return; |
3905 | } | 3914 | } |
@@ -4289,7 +4298,7 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
4289 | 4298 | ||
4290 | list_del_init(&ndlp->els_retry_evt.evt_listp); | 4299 | list_del_init(&ndlp->els_retry_evt.evt_listp); |
4291 | list_del_init(&ndlp->dev_loss_evt.evt_listp); | 4300 | list_del_init(&ndlp->dev_loss_evt.evt_listp); |
4292 | 4301 | lpfc_cleanup_vports_rrqs(vport, ndlp); | |
4293 | lpfc_unreg_rpi(vport, ndlp); | 4302 | lpfc_unreg_rpi(vport, ndlp); |
4294 | 4303 | ||
4295 | return 0; | 4304 | return 0; |
@@ -4426,10 +4435,11 @@ lpfc_findnode_did(struct lpfc_vport *vport, uint32_t did) | |||
4426 | { | 4435 | { |
4427 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 4436 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
4428 | struct lpfc_nodelist *ndlp; | 4437 | struct lpfc_nodelist *ndlp; |
4438 | unsigned long iflags; | ||
4429 | 4439 | ||
4430 | spin_lock_irq(shost->host_lock); | 4440 | spin_lock_irqsave(shost->host_lock, iflags); |
4431 | ndlp = __lpfc_findnode_did(vport, did); | 4441 | ndlp = __lpfc_findnode_did(vport, did); |
4432 | spin_unlock_irq(shost->host_lock); | 4442 | spin_unlock_irqrestore(shost->host_lock, iflags); |
4433 | return ndlp; | 4443 | return ndlp; |
4434 | } | 4444 | } |
4435 | 4445 | ||
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 96ed3ba6ba95..94ae37c5111a 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h | |||
@@ -341,6 +341,12 @@ struct csp { | |||
341 | uint8_t bbCreditMsb; | 341 | uint8_t bbCreditMsb; |
342 | uint8_t bbCreditlsb; /* FC Word 0, byte 3 */ | 342 | uint8_t bbCreditlsb; /* FC Word 0, byte 3 */ |
343 | 343 | ||
344 | /* | ||
345 | * Word 1 Bit 31 in common service parameter is overloaded. | ||
346 | * Word 1 Bit 31 in FLOGI request is multiple NPort request | ||
347 | * Word 1 Bit 31 in FLOGI response is clean address bit | ||
348 | */ | ||
349 | #define clean_address_bit request_multiple_Nport /* Word 1, bit 31 */ | ||
344 | #ifdef __BIG_ENDIAN_BITFIELD | 350 | #ifdef __BIG_ENDIAN_BITFIELD |
345 | uint16_t request_multiple_Nport:1; /* FC Word 1, bit 31 */ | 351 | uint16_t request_multiple_Nport:1; /* FC Word 1, bit 31 */ |
346 | uint16_t randomOffset:1; /* FC Word 1, bit 30 */ | 352 | uint16_t randomOffset:1; /* FC Word 1, bit 30 */ |
@@ -3198,7 +3204,10 @@ typedef struct { | |||
3198 | #define IOERR_SLER_RRQ_RJT_ERR 0x4C | 3204 | #define IOERR_SLER_RRQ_RJT_ERR 0x4C |
3199 | #define IOERR_SLER_RRQ_RETRY_ERR 0x4D | 3205 | #define IOERR_SLER_RRQ_RETRY_ERR 0x4D |
3200 | #define IOERR_SLER_ABTS_ERR 0x4E | 3206 | #define IOERR_SLER_ABTS_ERR 0x4E |
3201 | 3207 | #define IOERR_ELXSEC_KEY_UNWRAP_ERROR 0xF0 | |
3208 | #define IOERR_ELXSEC_KEY_UNWRAP_COMPARE_ERROR 0xF1 | ||
3209 | #define IOERR_ELXSEC_CRYPTO_ERROR 0xF2 | ||
3210 | #define IOERR_ELXSEC_CRYPTO_COMPARE_ERROR 0xF3 | ||
3202 | #define IOERR_DRVR_MASK 0x100 | 3211 | #define IOERR_DRVR_MASK 0x100 |
3203 | #define IOERR_SLI_DOWN 0x101 /* ulpStatus - Driver defined */ | 3212 | #define IOERR_SLI_DOWN 0x101 /* ulpStatus - Driver defined */ |
3204 | #define IOERR_SLI_BRESET 0x102 | 3213 | #define IOERR_SLI_BRESET 0x102 |
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 94c1aa1136de..c7178d60c7bf 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h | |||
@@ -778,6 +778,7 @@ struct mbox_header { | |||
778 | #define LPFC_MBOX_OPCODE_QUERY_FW_CFG 0x3A | 778 | #define LPFC_MBOX_OPCODE_QUERY_FW_CFG 0x3A |
779 | #define LPFC_MBOX_OPCODE_FUNCTION_RESET 0x3D | 779 | #define LPFC_MBOX_OPCODE_FUNCTION_RESET 0x3D |
780 | #define LPFC_MBOX_OPCODE_MQ_CREATE_EXT 0x5A | 780 | #define LPFC_MBOX_OPCODE_MQ_CREATE_EXT 0x5A |
781 | #define LPFC_MBOX_OPCODE_GET_SLI4_PARAMETERS 0xB5 | ||
781 | 782 | ||
782 | /* FCoE Opcodes */ | 783 | /* FCoE Opcodes */ |
783 | #define LPFC_MBOX_OPCODE_FCOE_WQ_CREATE 0x01 | 784 | #define LPFC_MBOX_OPCODE_FCOE_WQ_CREATE 0x01 |
@@ -1852,6 +1853,9 @@ struct lpfc_mbx_request_features { | |||
1852 | #define lpfc_mbx_rq_ftr_rq_ifip_SHIFT 7 | 1853 | #define lpfc_mbx_rq_ftr_rq_ifip_SHIFT 7 |
1853 | #define lpfc_mbx_rq_ftr_rq_ifip_MASK 0x00000001 | 1854 | #define lpfc_mbx_rq_ftr_rq_ifip_MASK 0x00000001 |
1854 | #define lpfc_mbx_rq_ftr_rq_ifip_WORD word2 | 1855 | #define lpfc_mbx_rq_ftr_rq_ifip_WORD word2 |
1856 | #define lpfc_mbx_rq_ftr_rq_perfh_SHIFT 11 | ||
1857 | #define lpfc_mbx_rq_ftr_rq_perfh_MASK 0x00000001 | ||
1858 | #define lpfc_mbx_rq_ftr_rq_perfh_WORD word2 | ||
1855 | uint32_t word3; | 1859 | uint32_t word3; |
1856 | #define lpfc_mbx_rq_ftr_rsp_iaab_SHIFT 0 | 1860 | #define lpfc_mbx_rq_ftr_rsp_iaab_SHIFT 0 |
1857 | #define lpfc_mbx_rq_ftr_rsp_iaab_MASK 0x00000001 | 1861 | #define lpfc_mbx_rq_ftr_rsp_iaab_MASK 0x00000001 |
@@ -1877,6 +1881,9 @@ struct lpfc_mbx_request_features { | |||
1877 | #define lpfc_mbx_rq_ftr_rsp_ifip_SHIFT 7 | 1881 | #define lpfc_mbx_rq_ftr_rsp_ifip_SHIFT 7 |
1878 | #define lpfc_mbx_rq_ftr_rsp_ifip_MASK 0x00000001 | 1882 | #define lpfc_mbx_rq_ftr_rsp_ifip_MASK 0x00000001 |
1879 | #define lpfc_mbx_rq_ftr_rsp_ifip_WORD word3 | 1883 | #define lpfc_mbx_rq_ftr_rsp_ifip_WORD word3 |
1884 | #define lpfc_mbx_rq_ftr_rsp_perfh_SHIFT 11 | ||
1885 | #define lpfc_mbx_rq_ftr_rsp_perfh_MASK 0x00000001 | ||
1886 | #define lpfc_mbx_rq_ftr_rsp_perfh_WORD word3 | ||
1880 | }; | 1887 | }; |
1881 | 1888 | ||
1882 | struct lpfc_mbx_supp_pages { | 1889 | struct lpfc_mbx_supp_pages { |
@@ -1935,7 +1942,7 @@ struct lpfc_mbx_supp_pages { | |||
1935 | #define LPFC_SLI4_PARAMETERS 2 | 1942 | #define LPFC_SLI4_PARAMETERS 2 |
1936 | }; | 1943 | }; |
1937 | 1944 | ||
1938 | struct lpfc_mbx_sli4_params { | 1945 | struct lpfc_mbx_pc_sli4_params { |
1939 | uint32_t word1; | 1946 | uint32_t word1; |
1940 | #define qs_SHIFT 0 | 1947 | #define qs_SHIFT 0 |
1941 | #define qs_MASK 0x00000001 | 1948 | #define qs_MASK 0x00000001 |
@@ -2051,6 +2058,88 @@ struct lpfc_mbx_sli4_params { | |||
2051 | uint32_t rsvd_13_63[51]; | 2058 | uint32_t rsvd_13_63[51]; |
2052 | }; | 2059 | }; |
2053 | 2060 | ||
2061 | struct lpfc_sli4_parameters { | ||
2062 | uint32_t word0; | ||
2063 | #define cfg_prot_type_SHIFT 0 | ||
2064 | #define cfg_prot_type_MASK 0x000000FF | ||
2065 | #define cfg_prot_type_WORD word0 | ||
2066 | uint32_t word1; | ||
2067 | #define cfg_ft_SHIFT 0 | ||
2068 | #define cfg_ft_MASK 0x00000001 | ||
2069 | #define cfg_ft_WORD word1 | ||
2070 | #define cfg_sli_rev_SHIFT 4 | ||
2071 | #define cfg_sli_rev_MASK 0x0000000f | ||
2072 | #define cfg_sli_rev_WORD word1 | ||
2073 | #define cfg_sli_family_SHIFT 8 | ||
2074 | #define cfg_sli_family_MASK 0x0000000f | ||
2075 | #define cfg_sli_family_WORD word1 | ||
2076 | #define cfg_if_type_SHIFT 12 | ||
2077 | #define cfg_if_type_MASK 0x0000000f | ||
2078 | #define cfg_if_type_WORD word1 | ||
2079 | #define cfg_sli_hint_1_SHIFT 16 | ||
2080 | #define cfg_sli_hint_1_MASK 0x000000ff | ||
2081 | #define cfg_sli_hint_1_WORD word1 | ||
2082 | #define cfg_sli_hint_2_SHIFT 24 | ||
2083 | #define cfg_sli_hint_2_MASK 0x0000001f | ||
2084 | #define cfg_sli_hint_2_WORD word1 | ||
2085 | uint32_t word2; | ||
2086 | uint32_t word3; | ||
2087 | uint32_t word4; | ||
2088 | #define cfg_cqv_SHIFT 14 | ||
2089 | #define cfg_cqv_MASK 0x00000003 | ||
2090 | #define cfg_cqv_WORD word4 | ||
2091 | uint32_t word5; | ||
2092 | uint32_t word6; | ||
2093 | #define cfg_mqv_SHIFT 14 | ||
2094 | #define cfg_mqv_MASK 0x00000003 | ||
2095 | #define cfg_mqv_WORD word6 | ||
2096 | uint32_t word7; | ||
2097 | uint32_t word8; | ||
2098 | #define cfg_wqv_SHIFT 14 | ||
2099 | #define cfg_wqv_MASK 0x00000003 | ||
2100 | #define cfg_wqv_WORD word8 | ||
2101 | uint32_t word9; | ||
2102 | uint32_t word10; | ||
2103 | #define cfg_rqv_SHIFT 14 | ||
2104 | #define cfg_rqv_MASK 0x00000003 | ||
2105 | #define cfg_rqv_WORD word10 | ||
2106 | uint32_t word11; | ||
2107 | #define cfg_rq_db_window_SHIFT 28 | ||
2108 | #define cfg_rq_db_window_MASK 0x0000000f | ||
2109 | #define cfg_rq_db_window_WORD word11 | ||
2110 | uint32_t word12; | ||
2111 | #define cfg_fcoe_SHIFT 0 | ||
2112 | #define cfg_fcoe_MASK 0x00000001 | ||
2113 | #define cfg_fcoe_WORD word12 | ||
2114 | #define cfg_phwq_SHIFT 15 | ||
2115 | #define cfg_phwq_MASK 0x00000001 | ||
2116 | #define cfg_phwq_WORD word12 | ||
2117 | #define cfg_loopbk_scope_SHIFT 28 | ||
2118 | #define cfg_loopbk_scope_MASK 0x0000000f | ||
2119 | #define cfg_loopbk_scope_WORD word12 | ||
2120 | uint32_t sge_supp_len; | ||
2121 | uint32_t word14; | ||
2122 | #define cfg_sgl_page_cnt_SHIFT 0 | ||
2123 | #define cfg_sgl_page_cnt_MASK 0x0000000f | ||
2124 | #define cfg_sgl_page_cnt_WORD word14 | ||
2125 | #define cfg_sgl_page_size_SHIFT 8 | ||
2126 | #define cfg_sgl_page_size_MASK 0x000000ff | ||
2127 | #define cfg_sgl_page_size_WORD word14 | ||
2128 | #define cfg_sgl_pp_align_SHIFT 16 | ||
2129 | #define cfg_sgl_pp_align_MASK 0x000000ff | ||
2130 | #define cfg_sgl_pp_align_WORD word14 | ||
2131 | uint32_t word15; | ||
2132 | uint32_t word16; | ||
2133 | uint32_t word17; | ||
2134 | uint32_t word18; | ||
2135 | uint32_t word19; | ||
2136 | }; | ||
2137 | |||
2138 | struct lpfc_mbx_get_sli4_parameters { | ||
2139 | struct mbox_header header; | ||
2140 | struct lpfc_sli4_parameters sli4_parameters; | ||
2141 | }; | ||
2142 | |||
2054 | /* Mailbox Completion Queue Error Messages */ | 2143 | /* Mailbox Completion Queue Error Messages */ |
2055 | #define MB_CQE_STATUS_SUCCESS 0x0 | 2144 | #define MB_CQE_STATUS_SUCCESS 0x0 |
2056 | #define MB_CQE_STATUS_INSUFFICIENT_PRIVILEGES 0x1 | 2145 | #define MB_CQE_STATUS_INSUFFICIENT_PRIVILEGES 0x1 |
@@ -2103,7 +2192,8 @@ struct lpfc_mqe { | |||
2103 | struct lpfc_mbx_post_hdr_tmpl hdr_tmpl; | 2192 | struct lpfc_mbx_post_hdr_tmpl hdr_tmpl; |
2104 | struct lpfc_mbx_query_fw_cfg query_fw_cfg; | 2193 | struct lpfc_mbx_query_fw_cfg query_fw_cfg; |
2105 | struct lpfc_mbx_supp_pages supp_pages; | 2194 | struct lpfc_mbx_supp_pages supp_pages; |
2106 | struct lpfc_mbx_sli4_params sli4_params; | 2195 | struct lpfc_mbx_pc_sli4_params sli4_params; |
2196 | struct lpfc_mbx_get_sli4_parameters get_sli4_parameters; | ||
2107 | struct lpfc_mbx_nop nop; | 2197 | struct lpfc_mbx_nop nop; |
2108 | } un; | 2198 | } un; |
2109 | }; | 2199 | }; |
@@ -2381,6 +2471,10 @@ struct wqe_common { | |||
2381 | #define wqe_wqes_SHIFT 15 | 2471 | #define wqe_wqes_SHIFT 15 |
2382 | #define wqe_wqes_MASK 0x00000001 | 2472 | #define wqe_wqes_MASK 0x00000001 |
2383 | #define wqe_wqes_WORD word10 | 2473 | #define wqe_wqes_WORD word10 |
2474 | /* Note that this field overlaps above fields */ | ||
2475 | #define wqe_wqid_SHIFT 1 | ||
2476 | #define wqe_wqid_MASK 0x0000007f | ||
2477 | #define wqe_wqid_WORD word10 | ||
2384 | #define wqe_pri_SHIFT 16 | 2478 | #define wqe_pri_SHIFT 16 |
2385 | #define wqe_pri_MASK 0x00000007 | 2479 | #define wqe_pri_MASK 0x00000007 |
2386 | #define wqe_pri_WORD word10 | 2480 | #define wqe_pri_WORD word10 |
@@ -2599,7 +2693,8 @@ struct fcp_iwrite64_wqe { | |||
2599 | uint32_t total_xfer_len; | 2693 | uint32_t total_xfer_len; |
2600 | uint32_t initial_xfer_len; | 2694 | uint32_t initial_xfer_len; |
2601 | struct wqe_common wqe_com; /* words 6-11 */ | 2695 | struct wqe_common wqe_com; /* words 6-11 */ |
2602 | uint32_t rsvd_12_15[4]; /* word 12-15 */ | 2696 | uint32_t rsrvd12; |
2697 | struct ulp_bde64 ph_bde; /* words 13-15 */ | ||
2603 | }; | 2698 | }; |
2604 | 2699 | ||
2605 | struct fcp_iread64_wqe { | 2700 | struct fcp_iread64_wqe { |
@@ -2608,7 +2703,8 @@ struct fcp_iread64_wqe { | |||
2608 | uint32_t total_xfer_len; /* word 4 */ | 2703 | uint32_t total_xfer_len; /* word 4 */ |
2609 | uint32_t rsrvd5; /* word 5 */ | 2704 | uint32_t rsrvd5; /* word 5 */ |
2610 | struct wqe_common wqe_com; /* words 6-11 */ | 2705 | struct wqe_common wqe_com; /* words 6-11 */ |
2611 | uint32_t rsvd_12_15[4]; /* word 12-15 */ | 2706 | uint32_t rsrvd12; |
2707 | struct ulp_bde64 ph_bde; /* words 13-15 */ | ||
2612 | }; | 2708 | }; |
2613 | 2709 | ||
2614 | struct fcp_icmnd64_wqe { | 2710 | struct fcp_icmnd64_wqe { |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 6d0b36aa3389..35665cfb5689 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -460,7 +460,7 @@ lpfc_config_port_post(struct lpfc_hba *phba) | |||
460 | || ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_16G) | 460 | || ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_16G) |
461 | && !(phba->lmt & LMT_16Gb))) { | 461 | && !(phba->lmt & LMT_16Gb))) { |
462 | /* Reset link speed to auto */ | 462 | /* Reset link speed to auto */ |
463 | lpfc_printf_log(phba, KERN_WARNING, LOG_LINK_EVENT, | 463 | lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT, |
464 | "1302 Invalid speed for this board: " | 464 | "1302 Invalid speed for this board: " |
465 | "Reset link speed to auto: x%x\n", | 465 | "Reset link speed to auto: x%x\n", |
466 | phba->cfg_link_speed); | 466 | phba->cfg_link_speed); |
@@ -945,17 +945,13 @@ static void | |||
945 | lpfc_rrq_timeout(unsigned long ptr) | 945 | lpfc_rrq_timeout(unsigned long ptr) |
946 | { | 946 | { |
947 | struct lpfc_hba *phba; | 947 | struct lpfc_hba *phba; |
948 | uint32_t tmo_posted; | ||
949 | unsigned long iflag; | 948 | unsigned long iflag; |
950 | 949 | ||
951 | phba = (struct lpfc_hba *)ptr; | 950 | phba = (struct lpfc_hba *)ptr; |
952 | spin_lock_irqsave(&phba->pport->work_port_lock, iflag); | 951 | spin_lock_irqsave(&phba->pport->work_port_lock, iflag); |
953 | tmo_posted = phba->hba_flag & HBA_RRQ_ACTIVE; | 952 | 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); | 953 | spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag); |
957 | if (!tmo_posted) | 954 | lpfc_worker_wake_up(phba); |
958 | lpfc_worker_wake_up(phba); | ||
959 | } | 955 | } |
960 | 956 | ||
961 | /** | 957 | /** |
@@ -2280,6 +2276,7 @@ lpfc_cleanup(struct lpfc_vport *vport) | |||
2280 | /* Wait for any activity on ndlps to settle */ | 2276 | /* Wait for any activity on ndlps to settle */ |
2281 | msleep(10); | 2277 | msleep(10); |
2282 | } | 2278 | } |
2279 | lpfc_cleanup_vports_rrqs(vport, NULL); | ||
2283 | } | 2280 | } |
2284 | 2281 | ||
2285 | /** | 2282 | /** |
@@ -2295,6 +2292,7 @@ lpfc_stop_vport_timers(struct lpfc_vport *vport) | |||
2295 | { | 2292 | { |
2296 | del_timer_sync(&vport->els_tmofunc); | 2293 | del_timer_sync(&vport->els_tmofunc); |
2297 | del_timer_sync(&vport->fc_fdmitmo); | 2294 | del_timer_sync(&vport->fc_fdmitmo); |
2295 | del_timer_sync(&vport->delayed_disc_tmo); | ||
2298 | lpfc_can_disctmo(vport); | 2296 | lpfc_can_disctmo(vport); |
2299 | return; | 2297 | return; |
2300 | } | 2298 | } |
@@ -2355,6 +2353,10 @@ lpfc_stop_hba_timers(struct lpfc_hba *phba) | |||
2355 | del_timer_sync(&phba->fabric_block_timer); | 2353 | del_timer_sync(&phba->fabric_block_timer); |
2356 | del_timer_sync(&phba->eratt_poll); | 2354 | del_timer_sync(&phba->eratt_poll); |
2357 | del_timer_sync(&phba->hb_tmofunc); | 2355 | del_timer_sync(&phba->hb_tmofunc); |
2356 | if (phba->sli_rev == LPFC_SLI_REV4) { | ||
2357 | del_timer_sync(&phba->rrq_tmr); | ||
2358 | phba->hba_flag &= ~HBA_RRQ_ACTIVE; | ||
2359 | } | ||
2358 | phba->hb_outstanding = 0; | 2360 | phba->hb_outstanding = 0; |
2359 | 2361 | ||
2360 | switch (phba->pci_dev_grp) { | 2362 | switch (phba->pci_dev_grp) { |
@@ -2732,6 +2734,11 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev) | |||
2732 | init_timer(&vport->els_tmofunc); | 2734 | init_timer(&vport->els_tmofunc); |
2733 | vport->els_tmofunc.function = lpfc_els_timeout; | 2735 | vport->els_tmofunc.function = lpfc_els_timeout; |
2734 | vport->els_tmofunc.data = (unsigned long)vport; | 2736 | vport->els_tmofunc.data = (unsigned long)vport; |
2737 | |||
2738 | init_timer(&vport->delayed_disc_tmo); | ||
2739 | vport->delayed_disc_tmo.function = lpfc_delayed_disc_tmo; | ||
2740 | vport->delayed_disc_tmo.data = (unsigned long)vport; | ||
2741 | |||
2735 | error = scsi_add_host_with_dma(shost, dev, &phba->pcidev->dev); | 2742 | error = scsi_add_host_with_dma(shost, dev, &phba->pcidev->dev); |
2736 | if (error) | 2743 | if (error) |
2737 | goto out_put_shost; | 2744 | goto out_put_shost; |
@@ -4283,36 +4290,37 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) | |||
4283 | goto out_free_bsmbx; | 4290 | goto out_free_bsmbx; |
4284 | } | 4291 | } |
4285 | 4292 | ||
4286 | /* Get the Supported Pages. It is always available. */ | 4293 | /* Get the Supported Pages if PORT_CAPABILITIES is supported by port. */ |
4287 | lpfc_supported_pages(mboxq); | 4294 | lpfc_supported_pages(mboxq); |
4288 | rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); | 4295 | rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); |
4289 | if (unlikely(rc)) { | 4296 | if (!rc) { |
4290 | rc = -EIO; | 4297 | mqe = &mboxq->u.mqe; |
4291 | mempool_free(mboxq, phba->mbox_mem_pool); | 4298 | memcpy(&pn_page[0], ((uint8_t *)&mqe->un.supp_pages.word3), |
4292 | goto out_free_bsmbx; | 4299 | LPFC_MAX_SUPPORTED_PAGES); |
4293 | } | 4300 | for (i = 0; i < LPFC_MAX_SUPPORTED_PAGES; i++) { |
4294 | 4301 | switch (pn_page[i]) { | |
4295 | mqe = &mboxq->u.mqe; | 4302 | case LPFC_SLI4_PARAMETERS: |
4296 | memcpy(&pn_page[0], ((uint8_t *)&mqe->un.supp_pages.word3), | 4303 | phba->sli4_hba.pc_sli4_params.supported = 1; |
4297 | LPFC_MAX_SUPPORTED_PAGES); | 4304 | break; |
4298 | for (i = 0; i < LPFC_MAX_SUPPORTED_PAGES; i++) { | 4305 | default: |
4299 | switch (pn_page[i]) { | 4306 | break; |
4300 | case LPFC_SLI4_PARAMETERS: | 4307 | } |
4301 | phba->sli4_hba.pc_sli4_params.supported = 1; | 4308 | } |
4302 | break; | 4309 | /* Read the port's SLI4 Parameters capabilities if supported. */ |
4303 | default: | 4310 | if (phba->sli4_hba.pc_sli4_params.supported) |
4304 | break; | 4311 | rc = lpfc_pc_sli4_params_get(phba, mboxq); |
4312 | if (rc) { | ||
4313 | mempool_free(mboxq, phba->mbox_mem_pool); | ||
4314 | rc = -EIO; | ||
4315 | goto out_free_bsmbx; | ||
4305 | } | 4316 | } |
4306 | } | 4317 | } |
4307 | 4318 | /* | |
4308 | /* Read the port's SLI4 Parameters capabilities if supported. */ | 4319 | * Get sli4 parameters that override parameters from Port capabilities. |
4309 | if (phba->sli4_hba.pc_sli4_params.supported) | 4320 | * If this call fails it is not a critical error so continue loading. |
4310 | rc = lpfc_pc_sli4_params_get(phba, mboxq); | 4321 | */ |
4322 | lpfc_get_sli4_parameters(phba, mboxq); | ||
4311 | mempool_free(mboxq, phba->mbox_mem_pool); | 4323 | mempool_free(mboxq, phba->mbox_mem_pool); |
4312 | if (rc) { | ||
4313 | rc = -EIO; | ||
4314 | goto out_free_bsmbx; | ||
4315 | } | ||
4316 | /* Create all the SLI4 queues */ | 4324 | /* Create all the SLI4 queues */ |
4317 | rc = lpfc_sli4_queue_create(phba); | 4325 | rc = lpfc_sli4_queue_create(phba); |
4318 | if (rc) | 4326 | if (rc) |
@@ -7810,7 +7818,7 @@ lpfc_pc_sli4_params_get(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | |||
7810 | mqe = &mboxq->u.mqe; | 7818 | mqe = &mboxq->u.mqe; |
7811 | 7819 | ||
7812 | /* Read the port's SLI4 Parameters port capabilities */ | 7820 | /* Read the port's SLI4 Parameters port capabilities */ |
7813 | lpfc_sli4_params(mboxq); | 7821 | lpfc_pc_sli4_params(mboxq); |
7814 | if (!phba->sli4_hba.intr_enable) | 7822 | if (!phba->sli4_hba.intr_enable) |
7815 | rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); | 7823 | rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); |
7816 | else { | 7824 | else { |
@@ -7854,6 +7862,66 @@ lpfc_pc_sli4_params_get(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | |||
7854 | } | 7862 | } |
7855 | 7863 | ||
7856 | /** | 7864 | /** |
7865 | * lpfc_get_sli4_parameters - Get the SLI4 Config PARAMETERS. | ||
7866 | * @phba: Pointer to HBA context object. | ||
7867 | * @mboxq: Pointer to the mailboxq memory for the mailbox command response. | ||
7868 | * | ||
7869 | * This function is called in the SLI4 code path to read the port's | ||
7870 | * sli4 capabilities. | ||
7871 | * | ||
7872 | * This function may be be called from any context that can block-wait | ||
7873 | * for the completion. The expectation is that this routine is called | ||
7874 | * typically from probe_one or from the online routine. | ||
7875 | **/ | ||
7876 | int | ||
7877 | lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | ||
7878 | { | ||
7879 | int rc; | ||
7880 | struct lpfc_mqe *mqe = &mboxq->u.mqe; | ||
7881 | struct lpfc_pc_sli4_params *sli4_params; | ||
7882 | int length; | ||
7883 | struct lpfc_sli4_parameters *mbx_sli4_parameters; | ||
7884 | |||
7885 | /* Read the port's SLI4 Config Parameters */ | ||
7886 | length = (sizeof(struct lpfc_mbx_get_sli4_parameters) - | ||
7887 | sizeof(struct lpfc_sli4_cfg_mhdr)); | ||
7888 | lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON, | ||
7889 | LPFC_MBOX_OPCODE_GET_SLI4_PARAMETERS, | ||
7890 | length, LPFC_SLI4_MBX_EMBED); | ||
7891 | if (!phba->sli4_hba.intr_enable) | ||
7892 | rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); | ||
7893 | else | ||
7894 | rc = lpfc_sli_issue_mbox_wait(phba, mboxq, | ||
7895 | lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG)); | ||
7896 | if (unlikely(rc)) | ||
7897 | return rc; | ||
7898 | sli4_params = &phba->sli4_hba.pc_sli4_params; | ||
7899 | mbx_sli4_parameters = &mqe->un.get_sli4_parameters.sli4_parameters; | ||
7900 | sli4_params->if_type = bf_get(cfg_if_type, mbx_sli4_parameters); | ||
7901 | sli4_params->sli_rev = bf_get(cfg_sli_rev, mbx_sli4_parameters); | ||
7902 | sli4_params->sli_family = bf_get(cfg_sli_family, mbx_sli4_parameters); | ||
7903 | sli4_params->featurelevel_1 = bf_get(cfg_sli_hint_1, | ||
7904 | mbx_sli4_parameters); | ||
7905 | sli4_params->featurelevel_2 = bf_get(cfg_sli_hint_2, | ||
7906 | mbx_sli4_parameters); | ||
7907 | if (bf_get(cfg_phwq, mbx_sli4_parameters)) | ||
7908 | phba->sli3_options |= LPFC_SLI4_PHWQ_ENABLED; | ||
7909 | else | ||
7910 | phba->sli3_options &= ~LPFC_SLI4_PHWQ_ENABLED; | ||
7911 | sli4_params->sge_supp_len = mbx_sli4_parameters->sge_supp_len; | ||
7912 | sli4_params->loopbk_scope = bf_get(loopbk_scope, mbx_sli4_parameters); | ||
7913 | sli4_params->cqv = bf_get(cfg_cqv, mbx_sli4_parameters); | ||
7914 | sli4_params->mqv = bf_get(cfg_mqv, mbx_sli4_parameters); | ||
7915 | sli4_params->wqv = bf_get(cfg_wqv, mbx_sli4_parameters); | ||
7916 | sli4_params->rqv = bf_get(cfg_rqv, mbx_sli4_parameters); | ||
7917 | sli4_params->sgl_pages_max = bf_get(cfg_sgl_page_cnt, | ||
7918 | mbx_sli4_parameters); | ||
7919 | sli4_params->sgl_pp_align = bf_get(cfg_sgl_pp_align, | ||
7920 | mbx_sli4_parameters); | ||
7921 | return 0; | ||
7922 | } | ||
7923 | |||
7924 | /** | ||
7857 | * lpfc_pci_probe_one_s3 - PCI probe func to reg SLI-3 device to PCI subsystem. | 7925 | * lpfc_pci_probe_one_s3 - PCI probe func to reg SLI-3 device to PCI subsystem. |
7858 | * @pdev: pointer to PCI device | 7926 | * @pdev: pointer to PCI device |
7859 | * @pid: pointer to PCI device identifier | 7927 | * @pid: pointer to PCI device identifier |
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 23403c650207..dba32dfdb59b 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c | |||
@@ -1263,7 +1263,8 @@ lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
1263 | if (phba->sli_rev == LPFC_SLI_REV3 && phba->vpd.sli3Feat.cerbm) { | 1263 | if (phba->sli_rev == LPFC_SLI_REV3 && phba->vpd.sli3Feat.cerbm) { |
1264 | if (phba->cfg_enable_bg) | 1264 | if (phba->cfg_enable_bg) |
1265 | mb->un.varCfgPort.cbg = 1; /* configure BlockGuard */ | 1265 | mb->un.varCfgPort.cbg = 1; /* configure BlockGuard */ |
1266 | mb->un.varCfgPort.cdss = 1; /* Configure Security */ | 1266 | if (phba->cfg_enable_dss) |
1267 | mb->un.varCfgPort.cdss = 1; /* Configure Security */ | ||
1267 | mb->un.varCfgPort.cerbm = 1; /* Request HBQs */ | 1268 | mb->un.varCfgPort.cerbm = 1; /* Request HBQs */ |
1268 | mb->un.varCfgPort.ccrp = 1; /* Command Ring Polling */ | 1269 | mb->un.varCfgPort.ccrp = 1; /* Command Ring Polling */ |
1269 | mb->un.varCfgPort.max_hbq = lpfc_sli_hbq_count(); | 1270 | mb->un.varCfgPort.max_hbq = lpfc_sli_hbq_count(); |
@@ -1692,7 +1693,7 @@ lpfc_sli4_mbox_cmd_free(struct lpfc_hba *phba, struct lpfcMboxq *mbox) | |||
1692 | * @mbox: pointer to lpfc mbox command. | 1693 | * @mbox: pointer to lpfc mbox command. |
1693 | * @subsystem: The sli4 config sub mailbox subsystem. | 1694 | * @subsystem: The sli4 config sub mailbox subsystem. |
1694 | * @opcode: The sli4 config sub mailbox command opcode. | 1695 | * @opcode: The sli4 config sub mailbox command opcode. |
1695 | * @length: Length of the sli4 config mailbox command. | 1696 | * @length: Length of the sli4 config mailbox command (including sub-header). |
1696 | * | 1697 | * |
1697 | * This routine sets up the header fields of SLI4 specific mailbox command | 1698 | * This routine sets up the header fields of SLI4 specific mailbox command |
1698 | * for sending IOCTL command. | 1699 | * for sending IOCTL command. |
@@ -1723,14 +1724,14 @@ lpfc_sli4_config(struct lpfc_hba *phba, struct lpfcMboxq *mbox, | |||
1723 | if (emb) { | 1724 | if (emb) { |
1724 | /* Set up main header fields */ | 1725 | /* Set up main header fields */ |
1725 | bf_set(lpfc_mbox_hdr_emb, &sli4_config->header.cfg_mhdr, 1); | 1726 | bf_set(lpfc_mbox_hdr_emb, &sli4_config->header.cfg_mhdr, 1); |
1726 | sli4_config->header.cfg_mhdr.payload_length = | 1727 | sli4_config->header.cfg_mhdr.payload_length = length; |
1727 | LPFC_MBX_CMD_HDR_LENGTH + length; | ||
1728 | /* Set up sub-header fields following main header */ | 1728 | /* Set up sub-header fields following main header */ |
1729 | bf_set(lpfc_mbox_hdr_opcode, | 1729 | bf_set(lpfc_mbox_hdr_opcode, |
1730 | &sli4_config->header.cfg_shdr.request, opcode); | 1730 | &sli4_config->header.cfg_shdr.request, opcode); |
1731 | bf_set(lpfc_mbox_hdr_subsystem, | 1731 | bf_set(lpfc_mbox_hdr_subsystem, |
1732 | &sli4_config->header.cfg_shdr.request, subsystem); | 1732 | &sli4_config->header.cfg_shdr.request, subsystem); |
1733 | sli4_config->header.cfg_shdr.request.request_length = length; | 1733 | sli4_config->header.cfg_shdr.request.request_length = |
1734 | length - LPFC_MBX_CMD_HDR_LENGTH; | ||
1734 | return length; | 1735 | return length; |
1735 | } | 1736 | } |
1736 | 1737 | ||
@@ -1902,6 +1903,7 @@ lpfc_request_features(struct lpfc_hba *phba, struct lpfcMboxq *mboxq) | |||
1902 | 1903 | ||
1903 | /* Set up host requested features. */ | 1904 | /* Set up host requested features. */ |
1904 | bf_set(lpfc_mbx_rq_ftr_rq_fcpi, &mboxq->u.mqe.un.req_ftrs, 1); | 1905 | bf_set(lpfc_mbx_rq_ftr_rq_fcpi, &mboxq->u.mqe.un.req_ftrs, 1); |
1906 | bf_set(lpfc_mbx_rq_ftr_rq_perfh, &mboxq->u.mqe.un.req_ftrs, 1); | ||
1905 | 1907 | ||
1906 | /* Enable DIF (block guard) only if configured to do so. */ | 1908 | /* Enable DIF (block guard) only if configured to do so. */ |
1907 | if (phba->cfg_enable_bg) | 1909 | if (phba->cfg_enable_bg) |
@@ -2159,17 +2161,16 @@ lpfc_supported_pages(struct lpfcMboxq *mbox) | |||
2159 | } | 2161 | } |
2160 | 2162 | ||
2161 | /** | 2163 | /** |
2162 | * lpfc_sli4_params - Initialize the PORT_CAPABILITIES SLI4 Params | 2164 | * lpfc_pc_sli4_params - Initialize the PORT_CAPABILITIES SLI4 Params mbox cmd. |
2163 | * mailbox command. | ||
2164 | * @mbox: pointer to lpfc mbox command to initialize. | 2165 | * @mbox: pointer to lpfc mbox command to initialize. |
2165 | * | 2166 | * |
2166 | * The PORT_CAPABILITIES SLI4 parameters mailbox command is issued to | 2167 | * The PORT_CAPABILITIES SLI4 parameters mailbox command is issued to |
2167 | * retrieve the particular SLI4 features supported by the port. | 2168 | * retrieve the particular SLI4 features supported by the port. |
2168 | **/ | 2169 | **/ |
2169 | void | 2170 | void |
2170 | lpfc_sli4_params(struct lpfcMboxq *mbox) | 2171 | lpfc_pc_sli4_params(struct lpfcMboxq *mbox) |
2171 | { | 2172 | { |
2172 | struct lpfc_mbx_sli4_params *sli4_params; | 2173 | struct lpfc_mbx_pc_sli4_params *sli4_params; |
2173 | 2174 | ||
2174 | memset(mbox, 0, sizeof(*mbox)); | 2175 | memset(mbox, 0, sizeof(*mbox)); |
2175 | sli4_params = &mbox->u.mqe.un.sli4_params; | 2176 | sli4_params = &mbox->u.mqe.un.sli4_params; |
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index d85a7423a694..52b35159fc35 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c | |||
@@ -350,7 +350,11 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
350 | ndlp->nlp_maxframe = | 350 | ndlp->nlp_maxframe = |
351 | ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb; | 351 | ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb; |
352 | 352 | ||
353 | /* no need to reg_login if we are already in one of these states */ | 353 | /* |
354 | * Need to unreg_login if we are already in one of these states and | ||
355 | * change to NPR state. This will block the port until after the ACC | ||
356 | * completes and the reg_login is issued and completed. | ||
357 | */ | ||
354 | switch (ndlp->nlp_state) { | 358 | switch (ndlp->nlp_state) { |
355 | case NLP_STE_NPR_NODE: | 359 | case NLP_STE_NPR_NODE: |
356 | if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) | 360 | if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) |
@@ -359,8 +363,9 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
359 | case NLP_STE_PRLI_ISSUE: | 363 | case NLP_STE_PRLI_ISSUE: |
360 | case NLP_STE_UNMAPPED_NODE: | 364 | case NLP_STE_UNMAPPED_NODE: |
361 | case NLP_STE_MAPPED_NODE: | 365 | case NLP_STE_MAPPED_NODE: |
362 | lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL); | 366 | lpfc_unreg_rpi(vport, ndlp); |
363 | return 1; | 367 | ndlp->nlp_prev_state = ndlp->nlp_state; |
368 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); | ||
364 | } | 369 | } |
365 | 370 | ||
366 | if ((vport->fc_flag & FC_PT2PT) && | 371 | if ((vport->fc_flag & FC_PT2PT) && |
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index c97751c95d77..bf34178b80bf 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
@@ -609,6 +609,32 @@ lpfc_new_scsi_buf_s3(struct lpfc_vport *vport, int num_to_alloc) | |||
609 | } | 609 | } |
610 | 610 | ||
611 | /** | 611 | /** |
612 | * lpfc_sli4_vport_delete_fcp_xri_aborted -Remove all ndlp references for vport | ||
613 | * @vport: pointer to lpfc vport data structure. | ||
614 | * | ||
615 | * This routine is invoked by the vport cleanup for deletions and the cleanup | ||
616 | * for an ndlp on removal. | ||
617 | **/ | ||
618 | void | ||
619 | lpfc_sli4_vport_delete_fcp_xri_aborted(struct lpfc_vport *vport) | ||
620 | { | ||
621 | struct lpfc_hba *phba = vport->phba; | ||
622 | struct lpfc_scsi_buf *psb, *next_psb; | ||
623 | unsigned long iflag = 0; | ||
624 | |||
625 | spin_lock_irqsave(&phba->hbalock, iflag); | ||
626 | spin_lock(&phba->sli4_hba.abts_scsi_buf_list_lock); | ||
627 | list_for_each_entry_safe(psb, next_psb, | ||
628 | &phba->sli4_hba.lpfc_abts_scsi_buf_list, list) { | ||
629 | if (psb->rdata && psb->rdata->pnode | ||
630 | && psb->rdata->pnode->vport == vport) | ||
631 | psb->rdata = NULL; | ||
632 | } | ||
633 | spin_unlock(&phba->sli4_hba.abts_scsi_buf_list_lock); | ||
634 | spin_unlock_irqrestore(&phba->hbalock, iflag); | ||
635 | } | ||
636 | |||
637 | /** | ||
612 | * lpfc_sli4_fcp_xri_aborted - Fast-path process of fcp xri abort | 638 | * lpfc_sli4_fcp_xri_aborted - Fast-path process of fcp xri abort |
613 | * @phba: pointer to lpfc hba data structure. | 639 | * @phba: pointer to lpfc hba data structure. |
614 | * @axri: pointer to the fcp xri abort wcqe structure. | 640 | * @axri: pointer to the fcp xri abort wcqe structure. |
@@ -640,7 +666,11 @@ lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba, | |||
640 | psb->status = IOSTAT_SUCCESS; | 666 | psb->status = IOSTAT_SUCCESS; |
641 | spin_unlock( | 667 | spin_unlock( |
642 | &phba->sli4_hba.abts_scsi_buf_list_lock); | 668 | &phba->sli4_hba.abts_scsi_buf_list_lock); |
643 | ndlp = psb->rdata->pnode; | 669 | if (psb->rdata && psb->rdata->pnode) |
670 | ndlp = psb->rdata->pnode; | ||
671 | else | ||
672 | ndlp = NULL; | ||
673 | |||
644 | rrq_empty = list_empty(&phba->active_rrq_list); | 674 | rrq_empty = list_empty(&phba->active_rrq_list); |
645 | spin_unlock_irqrestore(&phba->hbalock, iflag); | 675 | spin_unlock_irqrestore(&phba->hbalock, iflag); |
646 | if (ndlp) | 676 | if (ndlp) |
@@ -964,36 +994,29 @@ lpfc_get_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) | |||
964 | static struct lpfc_scsi_buf* | 994 | static struct lpfc_scsi_buf* |
965 | lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) | 995 | lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) |
966 | { | 996 | { |
967 | struct lpfc_scsi_buf *lpfc_cmd = NULL; | 997 | struct lpfc_scsi_buf *lpfc_cmd ; |
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; | 998 | unsigned long iflag = 0; |
971 | int found = 0; | 999 | int found = 0; |
972 | 1000 | ||
973 | spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag); | 1001 | spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag); |
974 | list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list); | 1002 | list_for_each_entry(lpfc_cmd, &phba->lpfc_scsi_buf_list, |
975 | spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag); | 1003 | list) { |
976 | while (!found && lpfc_cmd) { | ||
977 | if (lpfc_test_rrq_active(phba, ndlp, | 1004 | if (lpfc_test_rrq_active(phba, ndlp, |
978 | lpfc_cmd->cur_iocbq.sli4_xritag)) { | 1005 | lpfc_cmd->cur_iocbq.sli4_xritag)) |
979 | lpfc_release_scsi_buf_s4(phba, lpfc_cmd); | 1006 | continue; |
980 | spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag); | 1007 | list_del(&lpfc_cmd->list); |
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; | 1008 | found = 1; |
992 | lpfc_cmd->seg_cnt = 0; | 1009 | lpfc_cmd->seg_cnt = 0; |
993 | lpfc_cmd->nonsg_phys = 0; | 1010 | lpfc_cmd->nonsg_phys = 0; |
994 | lpfc_cmd->prot_seg_cnt = 0; | 1011 | lpfc_cmd->prot_seg_cnt = 0; |
1012 | break; | ||
995 | } | 1013 | } |
996 | return lpfc_cmd; | 1014 | spin_unlock_irqrestore(&phba->scsi_buf_list_lock, |
1015 | iflag); | ||
1016 | if (!found) | ||
1017 | return NULL; | ||
1018 | else | ||
1019 | return lpfc_cmd; | ||
997 | } | 1020 | } |
998 | /** | 1021 | /** |
999 | * lpfc_get_scsi_buf - Get a scsi buffer from lpfc_scsi_buf_list of the HBA | 1022 | * lpfc_get_scsi_buf - Get a scsi buffer from lpfc_scsi_buf_list of the HBA |
@@ -1981,12 +2004,14 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) | |||
1981 | struct scatterlist *sgel = NULL; | 2004 | struct scatterlist *sgel = NULL; |
1982 | struct fcp_cmnd *fcp_cmnd = lpfc_cmd->fcp_cmnd; | 2005 | struct fcp_cmnd *fcp_cmnd = lpfc_cmd->fcp_cmnd; |
1983 | struct sli4_sge *sgl = (struct sli4_sge *)lpfc_cmd->fcp_bpl; | 2006 | struct sli4_sge *sgl = (struct sli4_sge *)lpfc_cmd->fcp_bpl; |
2007 | struct sli4_sge *first_data_sgl; | ||
1984 | IOCB_t *iocb_cmd = &lpfc_cmd->cur_iocbq.iocb; | 2008 | IOCB_t *iocb_cmd = &lpfc_cmd->cur_iocbq.iocb; |
1985 | dma_addr_t physaddr; | 2009 | dma_addr_t physaddr; |
1986 | uint32_t num_bde = 0; | 2010 | uint32_t num_bde = 0; |
1987 | uint32_t dma_len; | 2011 | uint32_t dma_len; |
1988 | uint32_t dma_offset = 0; | 2012 | uint32_t dma_offset = 0; |
1989 | int nseg; | 2013 | int nseg; |
2014 | struct ulp_bde64 *bde; | ||
1990 | 2015 | ||
1991 | /* | 2016 | /* |
1992 | * There are three possibilities here - use scatter-gather segment, use | 2017 | * There are three possibilities here - use scatter-gather segment, use |
@@ -2011,7 +2036,7 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) | |||
2011 | bf_set(lpfc_sli4_sge_last, sgl, 0); | 2036 | bf_set(lpfc_sli4_sge_last, sgl, 0); |
2012 | sgl->word2 = cpu_to_le32(sgl->word2); | 2037 | sgl->word2 = cpu_to_le32(sgl->word2); |
2013 | sgl += 1; | 2038 | sgl += 1; |
2014 | 2039 | first_data_sgl = sgl; | |
2015 | lpfc_cmd->seg_cnt = nseg; | 2040 | lpfc_cmd->seg_cnt = nseg; |
2016 | if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) { | 2041 | if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) { |
2017 | lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9074 BLKGRD:" | 2042 | lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9074 BLKGRD:" |
@@ -2047,6 +2072,17 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) | |||
2047 | dma_offset += dma_len; | 2072 | dma_offset += dma_len; |
2048 | sgl++; | 2073 | sgl++; |
2049 | } | 2074 | } |
2075 | /* setup the performance hint (first data BDE) if enabled */ | ||
2076 | if (phba->sli3_options & LPFC_SLI4_PERFH_ENABLED) { | ||
2077 | bde = (struct ulp_bde64 *) | ||
2078 | &(iocb_cmd->unsli3.sli3Words[5]); | ||
2079 | bde->addrLow = first_data_sgl->addr_lo; | ||
2080 | bde->addrHigh = first_data_sgl->addr_hi; | ||
2081 | bde->tus.f.bdeSize = | ||
2082 | le32_to_cpu(first_data_sgl->sge_len); | ||
2083 | bde->tus.f.bdeFlags = BUFF_TYPE_BDE_64; | ||
2084 | bde->tus.w = cpu_to_le32(bde->tus.w); | ||
2085 | } | ||
2050 | } else { | 2086 | } else { |
2051 | sgl += 1; | 2087 | sgl += 1; |
2052 | /* clear the last flag in the fcp_rsp map entry */ | 2088 | /* clear the last flag in the fcp_rsp map entry */ |
@@ -2471,6 +2507,16 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, | |||
2471 | lpfc_worker_wake_up(phba); | 2507 | lpfc_worker_wake_up(phba); |
2472 | break; | 2508 | break; |
2473 | case IOSTAT_LOCAL_REJECT: | 2509 | case IOSTAT_LOCAL_REJECT: |
2510 | case IOSTAT_REMOTE_STOP: | ||
2511 | if (lpfc_cmd->result == IOERR_ELXSEC_KEY_UNWRAP_ERROR || | ||
2512 | lpfc_cmd->result == | ||
2513 | IOERR_ELXSEC_KEY_UNWRAP_COMPARE_ERROR || | ||
2514 | lpfc_cmd->result == IOERR_ELXSEC_CRYPTO_ERROR || | ||
2515 | lpfc_cmd->result == | ||
2516 | IOERR_ELXSEC_CRYPTO_COMPARE_ERROR) { | ||
2517 | cmd->result = ScsiResult(DID_NO_CONNECT, 0); | ||
2518 | break; | ||
2519 | } | ||
2474 | if (lpfc_cmd->result == IOERR_INVALID_RPI || | 2520 | if (lpfc_cmd->result == IOERR_INVALID_RPI || |
2475 | lpfc_cmd->result == IOERR_NO_RESOURCES || | 2521 | lpfc_cmd->result == IOERR_NO_RESOURCES || |
2476 | lpfc_cmd->result == IOERR_ABORT_REQUESTED || | 2522 | lpfc_cmd->result == IOERR_ABORT_REQUESTED || |
@@ -2478,7 +2524,6 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, | |||
2478 | cmd->result = ScsiResult(DID_REQUEUE, 0); | 2524 | cmd->result = ScsiResult(DID_REQUEUE, 0); |
2479 | break; | 2525 | break; |
2480 | } | 2526 | } |
2481 | |||
2482 | if ((lpfc_cmd->result == IOERR_RX_DMA_FAILED || | 2527 | if ((lpfc_cmd->result == IOERR_RX_DMA_FAILED || |
2483 | lpfc_cmd->result == IOERR_TX_DMA_FAILED) && | 2528 | lpfc_cmd->result == IOERR_TX_DMA_FAILED) && |
2484 | pIocbOut->iocb.unsli3.sli3_bg.bgstat) { | 2529 | pIocbOut->iocb.unsli3.sli3_bg.bgstat) { |
@@ -2497,7 +2542,17 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, | |||
2497 | "on unprotected cmd\n"); | 2542 | "on unprotected cmd\n"); |
2498 | } | 2543 | } |
2499 | } | 2544 | } |
2500 | 2545 | if ((lpfc_cmd->status == IOSTAT_REMOTE_STOP) | |
2546 | && (phba->sli_rev == LPFC_SLI_REV4) | ||
2547 | && (pnode && NLP_CHK_NODE_ACT(pnode))) { | ||
2548 | /* This IO was aborted by the target, we don't | ||
2549 | * know the rxid and because we did not send the | ||
2550 | * ABTS we cannot generate and RRQ. | ||
2551 | */ | ||
2552 | lpfc_set_rrq_active(phba, pnode, | ||
2553 | lpfc_cmd->cur_iocbq.sli4_xritag, | ||
2554 | 0, 0); | ||
2555 | } | ||
2501 | /* else: fall through */ | 2556 | /* else: fall through */ |
2502 | default: | 2557 | default: |
2503 | cmd->result = ScsiResult(DID_ERROR, 0); | 2558 | cmd->result = ScsiResult(DID_ERROR, 0); |
@@ -2508,9 +2563,8 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, | |||
2508 | || (pnode->nlp_state != NLP_STE_MAPPED_NODE)) | 2563 | || (pnode->nlp_state != NLP_STE_MAPPED_NODE)) |
2509 | cmd->result = ScsiResult(DID_TRANSPORT_DISRUPTED, | 2564 | cmd->result = ScsiResult(DID_TRANSPORT_DISRUPTED, |
2510 | SAM_STAT_BUSY); | 2565 | SAM_STAT_BUSY); |
2511 | } else { | 2566 | } else |
2512 | cmd->result = ScsiResult(DID_OK, 0); | 2567 | cmd->result = ScsiResult(DID_OK, 0); |
2513 | } | ||
2514 | 2568 | ||
2515 | if (cmd->result || lpfc_cmd->fcp_rsp->rspSnsLen) { | 2569 | if (cmd->result || lpfc_cmd->fcp_rsp->rspSnsLen) { |
2516 | uint32_t *lp = (uint32_t *)cmd->sense_buffer; | 2570 | uint32_t *lp = (uint32_t *)cmd->sense_buffer; |
@@ -3004,11 +3058,11 @@ lpfc_queuecommand_lck(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) | |||
3004 | * transport is still transitioning. | 3058 | * transport is still transitioning. |
3005 | */ | 3059 | */ |
3006 | if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) { | 3060 | if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) { |
3007 | cmnd->result = ScsiResult(DID_TRANSPORT_DISRUPTED, 0); | 3061 | cmnd->result = ScsiResult(DID_IMM_RETRY, 0); |
3008 | goto out_fail_command; | 3062 | goto out_fail_command; |
3009 | } | 3063 | } |
3010 | if (atomic_read(&ndlp->cmd_pending) >= ndlp->cmd_qdepth) | 3064 | if (atomic_read(&ndlp->cmd_pending) >= ndlp->cmd_qdepth) |
3011 | goto out_host_busy; | 3065 | goto out_tgt_busy; |
3012 | 3066 | ||
3013 | lpfc_cmd = lpfc_get_scsi_buf(phba, ndlp); | 3067 | lpfc_cmd = lpfc_get_scsi_buf(phba, ndlp); |
3014 | if (lpfc_cmd == NULL) { | 3068 | if (lpfc_cmd == NULL) { |
@@ -3125,6 +3179,9 @@ lpfc_queuecommand_lck(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) | |||
3125 | out_host_busy: | 3179 | out_host_busy: |
3126 | return SCSI_MLQUEUE_HOST_BUSY; | 3180 | return SCSI_MLQUEUE_HOST_BUSY; |
3127 | 3181 | ||
3182 | out_tgt_busy: | ||
3183 | return SCSI_MLQUEUE_TARGET_BUSY; | ||
3184 | |||
3128 | out_fail_command: | 3185 | out_fail_command: |
3129 | done(cmnd); | 3186 | done(cmnd); |
3130 | return 0; | 3187 | return 0; |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index a359d2b873ce..2ee0374a9908 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -96,7 +96,8 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe *wqe) | |||
96 | /* set consumption flag every once in a while */ | 96 | /* set consumption flag every once in a while */ |
97 | if (!((q->host_index + 1) % LPFC_RELEASE_NOTIFICATION_INTERVAL)) | 97 | if (!((q->host_index + 1) % LPFC_RELEASE_NOTIFICATION_INTERVAL)) |
98 | bf_set(wqe_wqec, &wqe->generic.wqe_com, 1); | 98 | bf_set(wqe_wqec, &wqe->generic.wqe_com, 1); |
99 | 99 | if (q->phba->sli3_options & LPFC_SLI4_PHWQ_ENABLED) | |
100 | bf_set(wqe_wqid, &wqe->generic.wqe_com, q->queue_id); | ||
100 | lpfc_sli_pcimem_bcopy(wqe, temp_wqe, q->entry_size); | 101 | lpfc_sli_pcimem_bcopy(wqe, temp_wqe, q->entry_size); |
101 | 102 | ||
102 | /* Update the host index before invoking device */ | 103 | /* Update the host index before invoking device */ |
@@ -534,15 +535,35 @@ __lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | |||
534 | uint16_t adj_xri; | 535 | uint16_t adj_xri; |
535 | struct lpfc_node_rrq *rrq; | 536 | struct lpfc_node_rrq *rrq; |
536 | int empty; | 537 | int empty; |
538 | uint32_t did = 0; | ||
539 | |||
540 | |||
541 | if (!ndlp) | ||
542 | return -EINVAL; | ||
543 | |||
544 | if (!phba->cfg_enable_rrq) | ||
545 | return -EINVAL; | ||
546 | |||
547 | if (phba->pport->load_flag & FC_UNLOADING) { | ||
548 | phba->hba_flag &= ~HBA_RRQ_ACTIVE; | ||
549 | goto out; | ||
550 | } | ||
551 | did = ndlp->nlp_DID; | ||
537 | 552 | ||
538 | /* | 553 | /* |
539 | * set the active bit even if there is no mem available. | 554 | * set the active bit even if there is no mem available. |
540 | */ | 555 | */ |
541 | adj_xri = xritag - phba->sli4_hba.max_cfg_param.xri_base; | 556 | adj_xri = xritag - phba->sli4_hba.max_cfg_param.xri_base; |
542 | if (!ndlp) | 557 | |
543 | return -EINVAL; | 558 | if (NLP_CHK_FREE_REQ(ndlp)) |
559 | goto out; | ||
560 | |||
561 | if (ndlp->vport && (ndlp->vport->load_flag & FC_UNLOADING)) | ||
562 | goto out; | ||
563 | |||
544 | if (test_and_set_bit(adj_xri, ndlp->active_rrqs.xri_bitmap)) | 564 | if (test_and_set_bit(adj_xri, ndlp->active_rrqs.xri_bitmap)) |
545 | return -EINVAL; | 565 | goto out; |
566 | |||
546 | rrq = mempool_alloc(phba->rrq_pool, GFP_KERNEL); | 567 | rrq = mempool_alloc(phba->rrq_pool, GFP_KERNEL); |
547 | if (rrq) { | 568 | if (rrq) { |
548 | rrq->send_rrq = send_rrq; | 569 | rrq->send_rrq = send_rrq; |
@@ -553,14 +574,7 @@ __lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | |||
553 | rrq->vport = ndlp->vport; | 574 | rrq->vport = ndlp->vport; |
554 | rrq->rxid = rxid; | 575 | rrq->rxid = rxid; |
555 | empty = list_empty(&phba->active_rrq_list); | 576 | empty = list_empty(&phba->active_rrq_list); |
556 | if (phba->cfg_enable_rrq && send_rrq) | 577 | rrq->send_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); | 578 | list_add_tail(&rrq->list, &phba->active_rrq_list); |
565 | if (!(phba->hba_flag & HBA_RRQ_ACTIVE)) { | 579 | if (!(phba->hba_flag & HBA_RRQ_ACTIVE)) { |
566 | phba->hba_flag |= HBA_RRQ_ACTIVE; | 580 | phba->hba_flag |= HBA_RRQ_ACTIVE; |
@@ -569,40 +583,49 @@ __lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | |||
569 | } | 583 | } |
570 | return 0; | 584 | return 0; |
571 | } | 585 | } |
572 | return -ENOMEM; | 586 | out: |
587 | lpfc_printf_log(phba, KERN_INFO, LOG_SLI, | ||
588 | "2921 Can't set rrq active xri:0x%x rxid:0x%x" | ||
589 | " DID:0x%x Send:%d\n", | ||
590 | xritag, rxid, did, send_rrq); | ||
591 | return -EINVAL; | ||
573 | } | 592 | } |
574 | 593 | ||
575 | /** | 594 | /** |
576 | * __lpfc_clr_rrq_active - Clears RRQ active bit in xri_bitmap. | 595 | * lpfc_clr_rrq_active - Clears RRQ active bit in xri_bitmap. |
577 | * @phba: Pointer to HBA context object. | 596 | * @phba: Pointer to HBA context object. |
578 | * @xritag: xri used in this exchange. | 597 | * @xritag: xri used in this exchange. |
579 | * @rrq: The RRQ to be cleared. | 598 | * @rrq: The RRQ to be cleared. |
580 | * | 599 | * |
581 | * This function is called with hbalock held. This function | ||
582 | **/ | 600 | **/ |
583 | static void | 601 | void |
584 | __lpfc_clr_rrq_active(struct lpfc_hba *phba, | 602 | lpfc_clr_rrq_active(struct lpfc_hba *phba, |
585 | uint16_t xritag, | 603 | uint16_t xritag, |
586 | struct lpfc_node_rrq *rrq) | 604 | struct lpfc_node_rrq *rrq) |
587 | { | 605 | { |
588 | uint16_t adj_xri; | 606 | uint16_t adj_xri; |
589 | struct lpfc_nodelist *ndlp; | 607 | struct lpfc_nodelist *ndlp = NULL; |
590 | 608 | ||
591 | ndlp = lpfc_findnode_did(rrq->vport, rrq->nlp_DID); | 609 | if ((rrq->vport) && NLP_CHK_NODE_ACT(rrq->ndlp)) |
610 | ndlp = lpfc_findnode_did(rrq->vport, rrq->nlp_DID); | ||
592 | 611 | ||
593 | /* The target DID could have been swapped (cable swap) | 612 | /* The target DID could have been swapped (cable swap) |
594 | * we should use the ndlp from the findnode if it is | 613 | * we should use the ndlp from the findnode if it is |
595 | * available. | 614 | * available. |
596 | */ | 615 | */ |
597 | if (!ndlp) | 616 | if ((!ndlp) && rrq->ndlp) |
598 | ndlp = rrq->ndlp; | 617 | ndlp = rrq->ndlp; |
599 | 618 | ||
619 | if (!ndlp) | ||
620 | goto out; | ||
621 | |||
600 | adj_xri = xritag - phba->sli4_hba.max_cfg_param.xri_base; | 622 | adj_xri = xritag - phba->sli4_hba.max_cfg_param.xri_base; |
601 | if (test_and_clear_bit(adj_xri, ndlp->active_rrqs.xri_bitmap)) { | 623 | if (test_and_clear_bit(adj_xri, ndlp->active_rrqs.xri_bitmap)) { |
602 | rrq->send_rrq = 0; | 624 | rrq->send_rrq = 0; |
603 | rrq->xritag = 0; | 625 | rrq->xritag = 0; |
604 | rrq->rrq_stop_time = 0; | 626 | rrq->rrq_stop_time = 0; |
605 | } | 627 | } |
628 | out: | ||
606 | mempool_free(rrq, phba->rrq_pool); | 629 | mempool_free(rrq, phba->rrq_pool); |
607 | } | 630 | } |
608 | 631 | ||
@@ -627,34 +650,34 @@ lpfc_handle_rrq_active(struct lpfc_hba *phba) | |||
627 | struct lpfc_node_rrq *nextrrq; | 650 | struct lpfc_node_rrq *nextrrq; |
628 | unsigned long next_time; | 651 | unsigned long next_time; |
629 | unsigned long iflags; | 652 | unsigned long iflags; |
653 | LIST_HEAD(send_rrq); | ||
630 | 654 | ||
631 | spin_lock_irqsave(&phba->hbalock, iflags); | 655 | spin_lock_irqsave(&phba->hbalock, iflags); |
632 | phba->hba_flag &= ~HBA_RRQ_ACTIVE; | 656 | phba->hba_flag &= ~HBA_RRQ_ACTIVE; |
633 | next_time = jiffies + HZ * (phba->fc_ratov + 1); | 657 | next_time = jiffies + HZ * (phba->fc_ratov + 1); |
634 | list_for_each_entry_safe(rrq, nextrrq, | 658 | list_for_each_entry_safe(rrq, nextrrq, |
635 | &phba->active_rrq_list, list) { | 659 | &phba->active_rrq_list, list) { |
636 | if (time_after(jiffies, rrq->rrq_stop_time)) { | 660 | if (time_after(jiffies, rrq->rrq_stop_time)) |
637 | list_del(&rrq->list); | 661 | list_move(&rrq->list, &send_rrq); |
638 | if (!rrq->send_rrq) | 662 | else if (time_before(rrq->rrq_stop_time, next_time)) |
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; | 663 | next_time = rrq->rrq_stop_time; |
654 | } | 664 | } |
655 | spin_unlock_irqrestore(&phba->hbalock, iflags); | 665 | spin_unlock_irqrestore(&phba->hbalock, iflags); |
656 | if (!list_empty(&phba->active_rrq_list)) | 666 | if (!list_empty(&phba->active_rrq_list)) |
657 | mod_timer(&phba->rrq_tmr, next_time); | 667 | mod_timer(&phba->rrq_tmr, next_time); |
668 | list_for_each_entry_safe(rrq, nextrrq, &send_rrq, list) { | ||
669 | list_del(&rrq->list); | ||
670 | if (!rrq->send_rrq) | ||
671 | /* this call will free the rrq */ | ||
672 | lpfc_clr_rrq_active(phba, rrq->xritag, rrq); | ||
673 | else if (lpfc_send_rrq(phba, rrq)) { | ||
674 | /* if we send the rrq then the completion handler | ||
675 | * will clear the bit in the xribitmap. | ||
676 | */ | ||
677 | lpfc_clr_rrq_active(phba, rrq->xritag, | ||
678 | rrq); | ||
679 | } | ||
680 | } | ||
658 | } | 681 | } |
659 | 682 | ||
660 | /** | 683 | /** |
@@ -692,29 +715,37 @@ lpfc_get_active_rrq(struct lpfc_vport *vport, uint16_t xri, uint32_t did) | |||
692 | /** | 715 | /** |
693 | * lpfc_cleanup_vports_rrqs - Remove and clear the active RRQ for this vport. | 716 | * lpfc_cleanup_vports_rrqs - Remove and clear the active RRQ for this vport. |
694 | * @vport: Pointer to vport context object. | 717 | * @vport: Pointer to vport context object. |
695 | * | 718 | * @ndlp: Pointer to the lpfc_node_list structure. |
696 | * Remove all active RRQs for this vport from the phba->active_rrq_list and | 719 | * If ndlp is NULL Remove all active RRQs for this vport from the |
697 | * clear the rrq. | 720 | * phba->active_rrq_list and clear the rrq. |
721 | * If ndlp is not NULL then only remove rrqs for this vport & this ndlp. | ||
698 | **/ | 722 | **/ |
699 | void | 723 | void |
700 | lpfc_cleanup_vports_rrqs(struct lpfc_vport *vport) | 724 | lpfc_cleanup_vports_rrqs(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) |
701 | 725 | ||
702 | { | 726 | { |
703 | struct lpfc_hba *phba = vport->phba; | 727 | struct lpfc_hba *phba = vport->phba; |
704 | struct lpfc_node_rrq *rrq; | 728 | struct lpfc_node_rrq *rrq; |
705 | struct lpfc_node_rrq *nextrrq; | 729 | struct lpfc_node_rrq *nextrrq; |
706 | unsigned long iflags; | 730 | unsigned long iflags; |
731 | LIST_HEAD(rrq_list); | ||
707 | 732 | ||
708 | if (phba->sli_rev != LPFC_SLI_REV4) | 733 | if (phba->sli_rev != LPFC_SLI_REV4) |
709 | return; | 734 | return; |
710 | spin_lock_irqsave(&phba->hbalock, iflags); | 735 | if (!ndlp) { |
711 | list_for_each_entry_safe(rrq, nextrrq, &phba->active_rrq_list, list) { | 736 | lpfc_sli4_vport_delete_els_xri_aborted(vport); |
712 | if (rrq->vport == vport) { | 737 | lpfc_sli4_vport_delete_fcp_xri_aborted(vport); |
713 | list_del(&rrq->list); | ||
714 | __lpfc_clr_rrq_active(phba, rrq->xritag, rrq); | ||
715 | } | ||
716 | } | 738 | } |
739 | spin_lock_irqsave(&phba->hbalock, iflags); | ||
740 | list_for_each_entry_safe(rrq, nextrrq, &phba->active_rrq_list, list) | ||
741 | if ((rrq->vport == vport) && (!ndlp || rrq->ndlp == ndlp)) | ||
742 | list_move(&rrq->list, &rrq_list); | ||
717 | spin_unlock_irqrestore(&phba->hbalock, iflags); | 743 | spin_unlock_irqrestore(&phba->hbalock, iflags); |
744 | |||
745 | list_for_each_entry_safe(rrq, nextrrq, &rrq_list, list) { | ||
746 | list_del(&rrq->list); | ||
747 | lpfc_clr_rrq_active(phba, rrq->xritag, rrq); | ||
748 | } | ||
718 | } | 749 | } |
719 | 750 | ||
720 | /** | 751 | /** |
@@ -732,24 +763,27 @@ lpfc_cleanup_wt_rrqs(struct lpfc_hba *phba) | |||
732 | struct lpfc_node_rrq *nextrrq; | 763 | struct lpfc_node_rrq *nextrrq; |
733 | unsigned long next_time; | 764 | unsigned long next_time; |
734 | unsigned long iflags; | 765 | unsigned long iflags; |
766 | LIST_HEAD(rrq_list); | ||
735 | 767 | ||
736 | if (phba->sli_rev != LPFC_SLI_REV4) | 768 | if (phba->sli_rev != LPFC_SLI_REV4) |
737 | return; | 769 | return; |
738 | spin_lock_irqsave(&phba->hbalock, iflags); | 770 | spin_lock_irqsave(&phba->hbalock, iflags); |
739 | phba->hba_flag &= ~HBA_RRQ_ACTIVE; | 771 | phba->hba_flag &= ~HBA_RRQ_ACTIVE; |
740 | next_time = jiffies + HZ * (phba->fc_ratov * 2); | 772 | next_time = jiffies + HZ * (phba->fc_ratov * 2); |
741 | list_for_each_entry_safe(rrq, nextrrq, &phba->active_rrq_list, list) { | 773 | list_splice_init(&phba->active_rrq_list, &rrq_list); |
774 | spin_unlock_irqrestore(&phba->hbalock, iflags); | ||
775 | |||
776 | list_for_each_entry_safe(rrq, nextrrq, &rrq_list, list) { | ||
742 | list_del(&rrq->list); | 777 | list_del(&rrq->list); |
743 | __lpfc_clr_rrq_active(phba, rrq->xritag, rrq); | 778 | lpfc_clr_rrq_active(phba, rrq->xritag, rrq); |
744 | } | 779 | } |
745 | spin_unlock_irqrestore(&phba->hbalock, iflags); | ||
746 | if (!list_empty(&phba->active_rrq_list)) | 780 | if (!list_empty(&phba->active_rrq_list)) |
747 | mod_timer(&phba->rrq_tmr, next_time); | 781 | mod_timer(&phba->rrq_tmr, next_time); |
748 | } | 782 | } |
749 | 783 | ||
750 | 784 | ||
751 | /** | 785 | /** |
752 | * __lpfc_test_rrq_active - Test RRQ bit in xri_bitmap. | 786 | * lpfc_test_rrq_active - Test RRQ bit in xri_bitmap. |
753 | * @phba: Pointer to HBA context object. | 787 | * @phba: Pointer to HBA context object. |
754 | * @ndlp: Targets nodelist pointer for this exchange. | 788 | * @ndlp: Targets nodelist pointer for this exchange. |
755 | * @xritag the xri in the bitmap to test. | 789 | * @xritag the xri in the bitmap to test. |
@@ -758,8 +792,8 @@ lpfc_cleanup_wt_rrqs(struct lpfc_hba *phba) | |||
758 | * returns 0 = rrq not active for this xri | 792 | * returns 0 = rrq not active for this xri |
759 | * 1 = rrq is valid for this xri. | 793 | * 1 = rrq is valid for this xri. |
760 | **/ | 794 | **/ |
761 | static int | 795 | int |
762 | __lpfc_test_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | 796 | lpfc_test_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, |
763 | uint16_t xritag) | 797 | uint16_t xritag) |
764 | { | 798 | { |
765 | uint16_t adj_xri; | 799 | uint16_t adj_xri; |
@@ -802,52 +836,6 @@ lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | |||
802 | } | 836 | } |
803 | 837 | ||
804 | /** | 838 | /** |
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 | /** | ||
851 | * __lpfc_sli_get_sglq - Allocates an iocb object from sgl pool | 839 | * __lpfc_sli_get_sglq - Allocates an iocb object from sgl pool |
852 | * @phba: Pointer to HBA context object. | 840 | * @phba: Pointer to HBA context object. |
853 | * @piocb: Pointer to the iocbq. | 841 | * @piocb: Pointer to the iocbq. |
@@ -884,7 +872,7 @@ __lpfc_sli_get_sglq(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq) | |||
884 | return NULL; | 872 | return NULL; |
885 | adj_xri = sglq->sli4_xritag - | 873 | adj_xri = sglq->sli4_xritag - |
886 | phba->sli4_hba.max_cfg_param.xri_base; | 874 | phba->sli4_hba.max_cfg_param.xri_base; |
887 | if (__lpfc_test_rrq_active(phba, ndlp, sglq->sli4_xritag)) { | 875 | if (lpfc_test_rrq_active(phba, ndlp, sglq->sli4_xritag)) { |
888 | /* This xri has an rrq outstanding for this DID. | 876 | /* This xri has an rrq outstanding for this DID. |
889 | * put it back in the list and get another xri. | 877 | * put it back in the list and get another xri. |
890 | */ | 878 | */ |
@@ -969,7 +957,8 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) | |||
969 | } else { | 957 | } else { |
970 | sglq->state = SGL_FREED; | 958 | sglq->state = SGL_FREED; |
971 | sglq->ndlp = NULL; | 959 | sglq->ndlp = NULL; |
972 | list_add(&sglq->list, &phba->sli4_hba.lpfc_sgl_list); | 960 | list_add_tail(&sglq->list, |
961 | &phba->sli4_hba.lpfc_sgl_list); | ||
973 | 962 | ||
974 | /* Check if TXQ queue needs to be serviced */ | 963 | /* Check if TXQ queue needs to be serviced */ |
975 | if (pring->txq_cnt) | 964 | if (pring->txq_cnt) |
@@ -4817,7 +4806,10 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) | |||
4817 | "0378 No support for fcpi mode.\n"); | 4806 | "0378 No support for fcpi mode.\n"); |
4818 | ftr_rsp++; | 4807 | ftr_rsp++; |
4819 | } | 4808 | } |
4820 | 4809 | if (bf_get(lpfc_mbx_rq_ftr_rsp_perfh, &mqe->un.req_ftrs)) | |
4810 | phba->sli3_options |= LPFC_SLI4_PERFH_ENABLED; | ||
4811 | else | ||
4812 | phba->sli3_options &= ~LPFC_SLI4_PERFH_ENABLED; | ||
4821 | /* | 4813 | /* |
4822 | * If the port cannot support the host's requested features | 4814 | * If the port cannot support the host's requested features |
4823 | * then turn off the global config parameters to disable the | 4815 | * then turn off the global config parameters to disable the |
@@ -5004,7 +4996,8 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) | |||
5004 | spin_lock_irq(&phba->hbalock); | 4996 | spin_lock_irq(&phba->hbalock); |
5005 | phba->link_state = LPFC_LINK_DOWN; | 4997 | phba->link_state = LPFC_LINK_DOWN; |
5006 | spin_unlock_irq(&phba->hbalock); | 4998 | spin_unlock_irq(&phba->hbalock); |
5007 | rc = phba->lpfc_hba_init_link(phba, MBX_NOWAIT); | 4999 | if (phba->cfg_suppress_link_up == LPFC_INITIALIZE_LINK) |
5000 | rc = phba->lpfc_hba_init_link(phba, MBX_NOWAIT); | ||
5008 | out_unset_queue: | 5001 | out_unset_queue: |
5009 | /* Unset all the queues set up in this routine when error out */ | 5002 | /* Unset all the queues set up in this routine when error out */ |
5010 | if (rc) | 5003 | if (rc) |
@@ -10478,6 +10471,7 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq, | |||
10478 | cq->type = type; | 10471 | cq->type = type; |
10479 | cq->subtype = subtype; | 10472 | cq->subtype = subtype; |
10480 | cq->queue_id = bf_get(lpfc_mbx_cq_create_q_id, &cq_create->u.response); | 10473 | cq->queue_id = bf_get(lpfc_mbx_cq_create_q_id, &cq_create->u.response); |
10474 | cq->assoc_qid = eq->queue_id; | ||
10481 | cq->host_index = 0; | 10475 | cq->host_index = 0; |
10482 | cq->hba_index = 0; | 10476 | cq->hba_index = 0; |
10483 | 10477 | ||
@@ -10672,6 +10666,7 @@ lpfc_mq_create(struct lpfc_hba *phba, struct lpfc_queue *mq, | |||
10672 | goto out; | 10666 | goto out; |
10673 | } | 10667 | } |
10674 | mq->type = LPFC_MQ; | 10668 | mq->type = LPFC_MQ; |
10669 | mq->assoc_qid = cq->queue_id; | ||
10675 | mq->subtype = subtype; | 10670 | mq->subtype = subtype; |
10676 | mq->host_index = 0; | 10671 | mq->host_index = 0; |
10677 | mq->hba_index = 0; | 10672 | mq->hba_index = 0; |
@@ -10759,6 +10754,7 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq, | |||
10759 | goto out; | 10754 | goto out; |
10760 | } | 10755 | } |
10761 | wq->type = LPFC_WQ; | 10756 | wq->type = LPFC_WQ; |
10757 | wq->assoc_qid = cq->queue_id; | ||
10762 | wq->subtype = subtype; | 10758 | wq->subtype = subtype; |
10763 | wq->host_index = 0; | 10759 | wq->host_index = 0; |
10764 | wq->hba_index = 0; | 10760 | wq->hba_index = 0; |
@@ -10876,6 +10872,7 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq, | |||
10876 | goto out; | 10872 | goto out; |
10877 | } | 10873 | } |
10878 | hrq->type = LPFC_HRQ; | 10874 | hrq->type = LPFC_HRQ; |
10875 | hrq->assoc_qid = cq->queue_id; | ||
10879 | hrq->subtype = subtype; | 10876 | hrq->subtype = subtype; |
10880 | hrq->host_index = 0; | 10877 | hrq->host_index = 0; |
10881 | hrq->hba_index = 0; | 10878 | hrq->hba_index = 0; |
@@ -10936,6 +10933,7 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq, | |||
10936 | goto out; | 10933 | goto out; |
10937 | } | 10934 | } |
10938 | drq->type = LPFC_DRQ; | 10935 | drq->type = LPFC_DRQ; |
10936 | drq->assoc_qid = cq->queue_id; | ||
10939 | drq->subtype = subtype; | 10937 | drq->subtype = subtype; |
10940 | drq->host_index = 0; | 10938 | drq->host_index = 0; |
10941 | drq->hba_index = 0; | 10939 | drq->hba_index = 0; |
@@ -11189,7 +11187,7 @@ lpfc_rq_destroy(struct lpfc_hba *phba, struct lpfc_queue *hrq, | |||
11189 | if (!mbox) | 11187 | if (!mbox) |
11190 | return -ENOMEM; | 11188 | return -ENOMEM; |
11191 | length = (sizeof(struct lpfc_mbx_rq_destroy) - | 11189 | length = (sizeof(struct lpfc_mbx_rq_destroy) - |
11192 | sizeof(struct mbox_header)); | 11190 | sizeof(struct lpfc_sli4_cfg_mhdr)); |
11193 | lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_FCOE, | 11191 | lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_FCOE, |
11194 | LPFC_MBOX_OPCODE_FCOE_RQ_DESTROY, | 11192 | LPFC_MBOX_OPCODE_FCOE_RQ_DESTROY, |
11195 | length, LPFC_SLI4_MBX_EMBED); | 11193 | length, LPFC_SLI4_MBX_EMBED); |
@@ -11279,7 +11277,7 @@ lpfc_sli4_post_sgl(struct lpfc_hba *phba, | |||
11279 | lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_FCOE, | 11277 | lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_FCOE, |
11280 | LPFC_MBOX_OPCODE_FCOE_POST_SGL_PAGES, | 11278 | LPFC_MBOX_OPCODE_FCOE_POST_SGL_PAGES, |
11281 | sizeof(struct lpfc_mbx_post_sgl_pages) - | 11279 | sizeof(struct lpfc_mbx_post_sgl_pages) - |
11282 | sizeof(struct mbox_header), LPFC_SLI4_MBX_EMBED); | 11280 | sizeof(struct lpfc_sli4_cfg_mhdr), LPFC_SLI4_MBX_EMBED); |
11283 | 11281 | ||
11284 | post_sgl_pages = (struct lpfc_mbx_post_sgl_pages *) | 11282 | post_sgl_pages = (struct lpfc_mbx_post_sgl_pages *) |
11285 | &mbox->u.mqe.un.post_sgl_pages; | 11283 | &mbox->u.mqe.un.post_sgl_pages; |
@@ -12402,7 +12400,8 @@ lpfc_sli4_post_rpi_hdr(struct lpfc_hba *phba, struct lpfc_rpi_hdr *rpi_page) | |||
12402 | lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_FCOE, | 12400 | lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_FCOE, |
12403 | LPFC_MBOX_OPCODE_FCOE_POST_HDR_TEMPLATE, | 12401 | LPFC_MBOX_OPCODE_FCOE_POST_HDR_TEMPLATE, |
12404 | sizeof(struct lpfc_mbx_post_hdr_tmpl) - | 12402 | sizeof(struct lpfc_mbx_post_hdr_tmpl) - |
12405 | sizeof(struct mbox_header), LPFC_SLI4_MBX_EMBED); | 12403 | sizeof(struct lpfc_sli4_cfg_mhdr), |
12404 | LPFC_SLI4_MBX_EMBED); | ||
12406 | bf_set(lpfc_mbx_post_hdr_tmpl_page_cnt, | 12405 | bf_set(lpfc_mbx_post_hdr_tmpl_page_cnt, |
12407 | hdr_tmpl, rpi_page->page_count); | 12406 | hdr_tmpl, rpi_page->page_count); |
12408 | bf_set(lpfc_mbx_post_hdr_tmpl_rpi_offset, hdr_tmpl, | 12407 | bf_set(lpfc_mbx_post_hdr_tmpl_rpi_offset, hdr_tmpl, |
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index c7217d579e0f..595056b89608 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h | |||
@@ -125,9 +125,9 @@ struct lpfc_queue { | |||
125 | uint32_t entry_count; /* Number of entries to support on the queue */ | 125 | uint32_t entry_count; /* Number of entries to support on the queue */ |
126 | uint32_t entry_size; /* Size of each queue entry. */ | 126 | uint32_t entry_size; /* Size of each queue entry. */ |
127 | uint32_t queue_id; /* Queue ID assigned by the hardware */ | 127 | uint32_t queue_id; /* Queue ID assigned by the hardware */ |
128 | uint32_t assoc_qid; /* Queue ID associated with, for CQ/WQ/MQ */ | ||
128 | struct list_head page_list; | 129 | struct list_head page_list; |
129 | uint32_t page_count; /* Number of pages allocated for this queue */ | 130 | uint32_t page_count; /* Number of pages allocated for this queue */ |
130 | |||
131 | uint32_t host_index; /* The host's index for putting or getting */ | 131 | uint32_t host_index; /* The host's index for putting or getting */ |
132 | uint32_t hba_index; /* The last known hba index for get or put */ | 132 | uint32_t hba_index; /* The last known hba index for get or put */ |
133 | union sli4_qe qe[1]; /* array to index entries (must be last) */ | 133 | union sli4_qe qe[1]; /* array to index entries (must be last) */ |
@@ -359,6 +359,10 @@ struct lpfc_pc_sli4_params { | |||
359 | uint32_t hdr_pp_align; | 359 | uint32_t hdr_pp_align; |
360 | uint32_t sgl_pages_max; | 360 | uint32_t sgl_pages_max; |
361 | uint32_t sgl_pp_align; | 361 | uint32_t sgl_pp_align; |
362 | uint8_t cqv; | ||
363 | uint8_t mqv; | ||
364 | uint8_t wqv; | ||
365 | uint8_t rqv; | ||
362 | }; | 366 | }; |
363 | 367 | ||
364 | /* SLI4 HBA data structure entries */ | 368 | /* SLI4 HBA data structure entries */ |
@@ -562,6 +566,8 @@ void lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *, | |||
562 | struct sli4_wcqe_xri_aborted *); | 566 | struct sli4_wcqe_xri_aborted *); |
563 | void lpfc_sli4_els_xri_aborted(struct lpfc_hba *, | 567 | void lpfc_sli4_els_xri_aborted(struct lpfc_hba *, |
564 | struct sli4_wcqe_xri_aborted *); | 568 | struct sli4_wcqe_xri_aborted *); |
569 | void lpfc_sli4_vport_delete_els_xri_aborted(struct lpfc_vport *); | ||
570 | void lpfc_sli4_vport_delete_fcp_xri_aborted(struct lpfc_vport *); | ||
565 | int lpfc_sli4_brdreset(struct lpfc_hba *); | 571 | int lpfc_sli4_brdreset(struct lpfc_hba *); |
566 | int lpfc_sli4_add_fcf_record(struct lpfc_hba *, struct fcf_record *); | 572 | int lpfc_sli4_add_fcf_record(struct lpfc_hba *, struct fcf_record *); |
567 | void lpfc_sli_remove_dflt_fcf(struct lpfc_hba *); | 573 | void lpfc_sli_remove_dflt_fcf(struct lpfc_hba *); |
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index 386cf92de492..0a4d376dbca5 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2004-2010 Emulex. All rights reserved. * | 4 | * Copyright (C) 2004-2011 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * * | 7 | * * |
@@ -18,7 +18,7 @@ | |||
18 | * included with this package. * | 18 | * included with this package. * |
19 | *******************************************************************/ | 19 | *******************************************************************/ |
20 | 20 | ||
21 | #define LPFC_DRIVER_VERSION "8.3.20" | 21 | #define LPFC_DRIVER_VERSION "8.3.21" |
22 | #define LPFC_DRIVER_NAME "lpfc" | 22 | #define LPFC_DRIVER_NAME "lpfc" |
23 | #define LPFC_SP_DRIVER_HANDLER_NAME "lpfc:sp" | 23 | #define LPFC_SP_DRIVER_HANDLER_NAME "lpfc:sp" |
24 | #define LPFC_FP_DRIVER_HANDLER_NAME "lpfc:fp" | 24 | #define LPFC_FP_DRIVER_HANDLER_NAME "lpfc:fp" |
diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index 6b8d2952e32f..30ba5440c67a 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c | |||
@@ -464,6 +464,7 @@ disable_vport(struct fc_vport *fc_vport) | |||
464 | struct lpfc_hba *phba = vport->phba; | 464 | struct lpfc_hba *phba = vport->phba; |
465 | struct lpfc_nodelist *ndlp = NULL, *next_ndlp = NULL; | 465 | struct lpfc_nodelist *ndlp = NULL, *next_ndlp = NULL; |
466 | long timeout; | 466 | long timeout; |
467 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
467 | 468 | ||
468 | ndlp = lpfc_findnode_did(vport, Fabric_DID); | 469 | ndlp = lpfc_findnode_did(vport, Fabric_DID); |
469 | if (ndlp && NLP_CHK_NODE_ACT(ndlp) | 470 | if (ndlp && NLP_CHK_NODE_ACT(ndlp) |
@@ -498,6 +499,9 @@ disable_vport(struct fc_vport *fc_vport) | |||
498 | * scsi_host_put() to release the vport. | 499 | * scsi_host_put() to release the vport. |
499 | */ | 500 | */ |
500 | lpfc_mbx_unreg_vpi(vport); | 501 | lpfc_mbx_unreg_vpi(vport); |
502 | spin_lock_irq(shost->host_lock); | ||
503 | vport->fc_flag |= FC_VPORT_NEEDS_INIT_VPI; | ||
504 | spin_unlock_irq(shost->host_lock); | ||
501 | 505 | ||
502 | lpfc_vport_set_state(vport, FC_VPORT_DISABLED); | 506 | lpfc_vport_set_state(vport, FC_VPORT_DISABLED); |
503 | lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, | 507 | lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, |