aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc
diff options
context:
space:
mode:
authorJames Smart <james.smart@emulex.com>2011-05-24 11:44:28 -0400
committerJames Bottomley <jbottomley@parallels.com>2011-05-26 23:49:39 -0400
commit7ad20aa9d39a525542b0840ac38bfc77be831e19 (patch)
tree9ab9318a9e5f600fef19fde9f085d5d145e2dd6d /drivers/scsi/lpfc
parent6d368e532168cb621731b3936945cd910cb25bd0 (diff)
[SCSI] lpfc 8.3.24: Extend BSG infrastructure and add link diagnostics
Extend BSG infrastructure and add link diagnostics: - Removed unnecessary copies in handling pass-through mbox cmds. - Add embedded SLI_CONFIG support for BSG. - Add multibuffer support. - Implemented the setting up and tearing down Lancer FC device for performing internal and external loopback diagnostic tests. - Implemented the driver support for performing new link diagnostic tests Signed-off-by: Alex Iannicelli <alex.iannicelli@emulex.com> Signed-off-by: James Smart <james.smart@emulex.com> Signed-off-by: James Bottomley <jbottomley@parallels.com>
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r--drivers/scsi/lpfc/lpfc.h38
-rw-r--r--drivers/scsi/lpfc/lpfc_bsg.c2105
-rw-r--r--drivers/scsi/lpfc/lpfc_bsg.h87
-rw-r--r--drivers/scsi/lpfc/lpfc_hw4.h82
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c8
5 files changed, 1917 insertions, 403 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index dfd9ace862e7..8ec2c86a49d4 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -487,6 +487,42 @@ struct unsol_rcv_ct_ctx {
487 (1 << LPFC_USER_LINK_SPEED_AUTO)) 487 (1 << LPFC_USER_LINK_SPEED_AUTO))
488#define LPFC_LINK_SPEED_STRING "0, 1, 2, 4, 8, 10, 16" 488#define LPFC_LINK_SPEED_STRING "0, 1, 2, 4, 8, 10, 16"
489 489
490enum nemb_type {
491 nemb_mse = 1,
492 nemb_hbd
493};
494
495enum mbox_type {
496 mbox_rd = 1,
497 mbox_wr
498};
499
500enum dma_type {
501 dma_mbox = 1,
502 dma_ebuf
503};
504
505enum sta_type {
506 sta_pre_addr = 1,
507 sta_pos_addr
508};
509
510struct lpfc_mbox_ext_buf_ctx {
511 uint32_t state;
512#define LPFC_BSG_MBOX_IDLE 0
513#define LPFC_BSG_MBOX_HOST 1
514#define LPFC_BSG_MBOX_PORT 2
515#define LPFC_BSG_MBOX_DONE 3
516#define LPFC_BSG_MBOX_ABTS 4
517 enum nemb_type nembType;
518 enum mbox_type mboxType;
519 uint32_t numBuf;
520 uint32_t mbxTag;
521 uint32_t seqNum;
522 struct lpfc_dmabuf *mbx_dmabuf;
523 struct list_head ext_dmabuf_list;
524};
525
490struct lpfc_hba { 526struct lpfc_hba {
491 /* SCSI interface function jump table entries */ 527 /* SCSI interface function jump table entries */
492 int (*lpfc_new_scsi_buf) 528 int (*lpfc_new_scsi_buf)
@@ -590,6 +626,7 @@ struct lpfc_hba {
590 626
591 MAILBOX_t *mbox; 627 MAILBOX_t *mbox;
592 uint32_t *mbox_ext; 628 uint32_t *mbox_ext;
629 struct lpfc_mbox_ext_buf_ctx mbox_ext_buf_ctx;
593 uint32_t ha_copy; 630 uint32_t ha_copy;
594 struct _PCB *pcb; 631 struct _PCB *pcb;
595 struct _IOCB *IOCBs; 632 struct _IOCB *IOCBs;
@@ -708,7 +745,6 @@ struct lpfc_hba {
708 uint32_t *hbq_get; /* Host mem address of HBQ get ptrs */ 745 uint32_t *hbq_get; /* Host mem address of HBQ get ptrs */
709 746
710 int brd_no; /* FC board number */ 747 int brd_no; /* FC board number */
711
712 char SerialNumber[32]; /* adapter Serial Number */ 748 char SerialNumber[32]; /* adapter Serial Number */
713 char OptionROMVersion[32]; /* adapter BIOS / Fcode version */ 749 char OptionROMVersion[32]; /* adapter BIOS / Fcode version */
714 char ModelDesc[256]; /* Model Description */ 750 char ModelDesc[256]; /* Model Description */
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index 080187b0e701..7fb0ba4cbfa7 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -23,6 +23,7 @@
23#include <linux/pci.h> 23#include <linux/pci.h>
24#include <linux/slab.h> 24#include <linux/slab.h>
25#include <linux/delay.h> 25#include <linux/delay.h>
26#include <linux/list.h>
26 27
27#include <scsi/scsi.h> 28#include <scsi/scsi.h>
28#include <scsi/scsi_host.h> 29#include <scsi/scsi_host.h>
@@ -79,8 +80,7 @@ struct lpfc_bsg_iocb {
79struct lpfc_bsg_mbox { 80struct lpfc_bsg_mbox {
80 LPFC_MBOXQ_t *pmboxq; 81 LPFC_MBOXQ_t *pmboxq;
81 MAILBOX_t *mb; 82 MAILBOX_t *mb;
82 struct lpfc_dmabuf *rxbmp; /* for BIU diags */ 83 struct lpfc_dmabuf *dmabuffers; /* for BIU diags */
83 struct lpfc_dmabufext *dmp; /* for BIU diags */
84 uint8_t *ext; /* extended mailbox data */ 84 uint8_t *ext; /* extended mailbox data */
85 uint32_t mbOffset; /* from app */ 85 uint32_t mbOffset; /* from app */
86 uint32_t inExtWLen; /* from app */ 86 uint32_t inExtWLen; /* from app */
@@ -1469,11 +1469,91 @@ send_mgmt_rsp_exit:
1469} 1469}
1470 1470
1471/** 1471/**
1472 * lpfc_bsg_diag_mode - process a LPFC_BSG_VENDOR_DIAG_MODE bsg vendor command 1472 * lpfc_bsg_diag_mode_enter - process preparing into device diag loopback mode
1473 * @phba: Pointer to HBA context object.
1474 * @job: LPFC_BSG_VENDOR_DIAG_MODE
1475 *
1476 * This function is responsible for preparing driver for diag loopback
1477 * on device.
1478 */
1479static int
1480lpfc_bsg_diag_mode_enter(struct lpfc_hba *phba, struct fc_bsg_job *job)
1481{
1482 struct lpfc_vport **vports;
1483 struct Scsi_Host *shost;
1484 struct lpfc_sli *psli;
1485 struct lpfc_sli_ring *pring;
1486 int i = 0;
1487
1488 psli = &phba->sli;
1489 if (!psli)
1490 return -ENODEV;
1491
1492 pring = &psli->ring[LPFC_FCP_RING];
1493 if (!pring)
1494 return -ENODEV;
1495
1496 if ((phba->link_state == LPFC_HBA_ERROR) ||
1497 (psli->sli_flag & LPFC_BLOCK_MGMT_IO) ||
1498 (!(psli->sli_flag & LPFC_SLI_ACTIVE)))
1499 return -EACCES;
1500
1501 vports = lpfc_create_vport_work_array(phba);
1502 if (vports) {
1503 for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
1504 shost = lpfc_shost_from_vport(vports[i]);
1505 scsi_block_requests(shost);
1506 }
1507 lpfc_destroy_vport_work_array(phba, vports);
1508 } else {
1509 shost = lpfc_shost_from_vport(phba->pport);
1510 scsi_block_requests(shost);
1511 }
1512
1513 while (pring->txcmplq_cnt) {
1514 if (i++ > 500) /* wait up to 5 seconds */
1515 break;
1516 msleep(10);
1517 }
1518 return 0;
1519}
1520
1521/**
1522 * lpfc_bsg_diag_mode_exit - exit process from device diag loopback mode
1523 * @phba: Pointer to HBA context object.
1524 * @job: LPFC_BSG_VENDOR_DIAG_MODE
1525 *
1526 * This function is responsible for driver exit processing of setting up
1527 * diag loopback mode on device.
1528 */
1529static void
1530lpfc_bsg_diag_mode_exit(struct lpfc_hba *phba)
1531{
1532 struct Scsi_Host *shost;
1533 struct lpfc_vport **vports;
1534 int i;
1535
1536 vports = lpfc_create_vport_work_array(phba);
1537 if (vports) {
1538 for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
1539 shost = lpfc_shost_from_vport(vports[i]);
1540 scsi_unblock_requests(shost);
1541 }
1542 lpfc_destroy_vport_work_array(phba, vports);
1543 } else {
1544 shost = lpfc_shost_from_vport(phba->pport);
1545 scsi_unblock_requests(shost);
1546 }
1547 return;
1548}
1549
1550/**
1551 * lpfc_sli3_bsg_diag_loopback_mode - process an sli3 bsg vendor command
1552 * @phba: Pointer to HBA context object.
1473 * @job: LPFC_BSG_VENDOR_DIAG_MODE 1553 * @job: LPFC_BSG_VENDOR_DIAG_MODE
1474 * 1554 *
1475 * This function is responsible for placing a port into diagnostic loopback 1555 * This function is responsible for placing an sli3 port into diagnostic
1476 * mode in order to perform a diagnostic loopback test. 1556 * loopback mode in order to perform a diagnostic loopback test.
1477 * All new scsi requests are blocked, a small delay is used to allow the 1557 * All new scsi requests are blocked, a small delay is used to allow the
1478 * scsi requests to complete then the link is brought down. If the link is 1558 * scsi requests to complete then the link is brought down. If the link is
1479 * is placed in loopback mode then scsi requests are again allowed 1559 * is placed in loopback mode then scsi requests are again allowed
@@ -1481,17 +1561,11 @@ send_mgmt_rsp_exit:
1481 * All of this is done in-line. 1561 * All of this is done in-line.
1482 */ 1562 */
1483static int 1563static int
1484lpfc_bsg_diag_mode(struct fc_bsg_job *job) 1564lpfc_sli3_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job)
1485{ 1565{
1486 struct Scsi_Host *shost = job->shost;
1487 struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata;
1488 struct lpfc_hba *phba = vport->phba;
1489 struct diag_mode_set *loopback_mode; 1566 struct diag_mode_set *loopback_mode;
1490 struct lpfc_sli *psli = &phba->sli;
1491 struct lpfc_sli_ring *pring = &psli->ring[LPFC_FCP_RING];
1492 uint32_t link_flags; 1567 uint32_t link_flags;
1493 uint32_t timeout; 1568 uint32_t timeout;
1494 struct lpfc_vport **vports;
1495 LPFC_MBOXQ_t *pmboxq; 1569 LPFC_MBOXQ_t *pmboxq;
1496 int mbxstatus; 1570 int mbxstatus;
1497 int i = 0; 1571 int i = 0;
@@ -1500,53 +1574,33 @@ lpfc_bsg_diag_mode(struct fc_bsg_job *job)
1500 /* no data to return just the return code */ 1574 /* no data to return just the return code */
1501 job->reply->reply_payload_rcv_len = 0; 1575 job->reply->reply_payload_rcv_len = 0;
1502 1576
1503 if (job->request_len < 1577 if (job->request_len < sizeof(struct fc_bsg_request) +
1504 sizeof(struct fc_bsg_request) + sizeof(struct diag_mode_set)) { 1578 sizeof(struct diag_mode_set)) {
1505 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC, 1579 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
1506 "2738 Received DIAG MODE request below minimum " 1580 "2738 Received DIAG MODE request size:%d "
1507 "size\n"); 1581 "below the minimum size:%d\n",
1582 job->request_len,
1583 (int)(sizeof(struct fc_bsg_request) +
1584 sizeof(struct diag_mode_set)));
1508 rc = -EINVAL; 1585 rc = -EINVAL;
1509 goto job_error; 1586 goto job_error;
1510 } 1587 }
1511 1588
1589 rc = lpfc_bsg_diag_mode_enter(phba, job);
1590 if (rc)
1591 goto job_error;
1592
1593 /* bring the link to diagnostic mode */
1512 loopback_mode = (struct diag_mode_set *) 1594 loopback_mode = (struct diag_mode_set *)
1513 job->request->rqst_data.h_vendor.vendor_cmd; 1595 job->request->rqst_data.h_vendor.vendor_cmd;
1514 link_flags = loopback_mode->type; 1596 link_flags = loopback_mode->type;
1515 timeout = loopback_mode->timeout * 100; 1597 timeout = loopback_mode->timeout * 100;
1516 1598
1517 if ((phba->link_state == LPFC_HBA_ERROR) ||
1518 (psli->sli_flag & LPFC_BLOCK_MGMT_IO) ||
1519 (!(psli->sli_flag & LPFC_SLI_ACTIVE))) {
1520 rc = -EACCES;
1521 goto job_error;
1522 }
1523
1524 pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); 1599 pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
1525 if (!pmboxq) { 1600 if (!pmboxq) {
1526 rc = -ENOMEM; 1601 rc = -ENOMEM;
1527 goto job_error; 1602 goto loopback_mode_exit;
1528 }
1529
1530 vports = lpfc_create_vport_work_array(phba);
1531 if (vports) {
1532 for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
1533 shost = lpfc_shost_from_vport(vports[i]);
1534 scsi_block_requests(shost);
1535 }
1536
1537 lpfc_destroy_vport_work_array(phba, vports);
1538 } else {
1539 shost = lpfc_shost_from_vport(phba->pport);
1540 scsi_block_requests(shost);
1541 } 1603 }
1542
1543 while (pring->txcmplq_cnt) {
1544 if (i++ > 500) /* wait up to 5 seconds */
1545 break;
1546
1547 msleep(10);
1548 }
1549
1550 memset((void *)pmboxq, 0, sizeof(LPFC_MBOXQ_t)); 1604 memset((void *)pmboxq, 0, sizeof(LPFC_MBOXQ_t));
1551 pmboxq->u.mb.mbxCommand = MBX_DOWN_LINK; 1605 pmboxq->u.mb.mbxCommand = MBX_DOWN_LINK;
1552 pmboxq->u.mb.mbxOwner = OWN_HOST; 1606 pmboxq->u.mb.mbxOwner = OWN_HOST;
@@ -1600,24 +1654,416 @@ lpfc_bsg_diag_mode(struct fc_bsg_job *job)
1600 rc = -ENODEV; 1654 rc = -ENODEV;
1601 1655
1602loopback_mode_exit: 1656loopback_mode_exit:
1603 vports = lpfc_create_vport_work_array(phba); 1657 lpfc_bsg_diag_mode_exit(phba);
1604 if (vports) { 1658
1605 for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) { 1659 /*
1606 shost = lpfc_shost_from_vport(vports[i]); 1660 * Let SLI layer release mboxq if mbox command completed after timeout.
1607 scsi_unblock_requests(shost); 1661 */
1662 if (mbxstatus != MBX_TIMEOUT)
1663 mempool_free(pmboxq, phba->mbox_mem_pool);
1664
1665job_error:
1666 /* make error code available to userspace */
1667 job->reply->result = rc;
1668 /* complete the job back to userspace if no error */
1669 if (rc == 0)
1670 job->job_done(job);
1671 return rc;
1672}
1673
1674/**
1675 * lpfc_sli4_bsg_set_link_diag_state - set sli4 link diag state
1676 * @phba: Pointer to HBA context object.
1677 * @diag: Flag for set link to diag or nomral operation state.
1678 *
1679 * This function is responsible for issuing a sli4 mailbox command for setting
1680 * link to either diag state or normal operation state.
1681 */
1682static int
1683lpfc_sli4_bsg_set_link_diag_state(struct lpfc_hba *phba, uint32_t diag)
1684{
1685 LPFC_MBOXQ_t *pmboxq;
1686 struct lpfc_mbx_set_link_diag_state *link_diag_state;
1687 uint32_t req_len, alloc_len;
1688 int mbxstatus = MBX_SUCCESS, rc;
1689
1690 pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
1691 if (!pmboxq)
1692 return -ENOMEM;
1693
1694 req_len = (sizeof(struct lpfc_mbx_set_link_diag_state) -
1695 sizeof(struct lpfc_sli4_cfg_mhdr));
1696 alloc_len = lpfc_sli4_config(phba, pmboxq, LPFC_MBOX_SUBSYSTEM_FCOE,
1697 LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_STATE,
1698 req_len, LPFC_SLI4_MBX_EMBED);
1699 if (alloc_len != req_len) {
1700 rc = -ENOMEM;
1701 goto link_diag_state_set_out;
1702 }
1703 link_diag_state = &pmboxq->u.mqe.un.link_diag_state;
1704 bf_set(lpfc_mbx_set_diag_state_link_num, &link_diag_state->u.req,
1705 phba->sli4_hba.link_state.number);
1706 bf_set(lpfc_mbx_set_diag_state_link_type, &link_diag_state->u.req,
1707 phba->sli4_hba.link_state.type);
1708 if (diag)
1709 bf_set(lpfc_mbx_set_diag_state_diag,
1710 &link_diag_state->u.req, 1);
1711 else
1712 bf_set(lpfc_mbx_set_diag_state_diag,
1713 &link_diag_state->u.req, 0);
1714
1715 mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, LPFC_MBOX_TMO);
1716
1717 if ((mbxstatus == MBX_SUCCESS) && (pmboxq->u.mb.mbxStatus == 0))
1718 rc = 0;
1719 else
1720 rc = -ENODEV;
1721
1722link_diag_state_set_out:
1723 if (pmboxq && (mbxstatus != MBX_TIMEOUT))
1724 mempool_free(pmboxq, phba->mbox_mem_pool);
1725
1726 return rc;
1727}
1728
1729/**
1730 * lpfc_sli4_bsg_diag_loopback_mode - process an sli4 bsg vendor command
1731 * @phba: Pointer to HBA context object.
1732 * @job: LPFC_BSG_VENDOR_DIAG_MODE
1733 *
1734 * This function is responsible for placing an sli4 port into diagnostic
1735 * loopback mode in order to perform a diagnostic loopback test.
1736 */
1737static int
1738lpfc_sli4_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job)
1739{
1740 struct diag_mode_set *loopback_mode;
1741 uint32_t link_flags, timeout, req_len, alloc_len;
1742 struct lpfc_mbx_set_link_diag_loopback *link_diag_loopback;
1743 LPFC_MBOXQ_t *pmboxq = NULL;
1744 int mbxstatus, i, rc = 0;
1745
1746 /* no data to return just the return code */
1747 job->reply->reply_payload_rcv_len = 0;
1748
1749 if (job->request_len < sizeof(struct fc_bsg_request) +
1750 sizeof(struct diag_mode_set)) {
1751 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
1752 "3011 Received DIAG MODE request size:%d "
1753 "below the minimum size:%d\n",
1754 job->request_len,
1755 (int)(sizeof(struct fc_bsg_request) +
1756 sizeof(struct diag_mode_set)));
1757 rc = -EINVAL;
1758 goto job_error;
1759 }
1760
1761 rc = lpfc_bsg_diag_mode_enter(phba, job);
1762 if (rc)
1763 goto job_error;
1764
1765 /* bring the link to diagnostic mode */
1766 loopback_mode = (struct diag_mode_set *)
1767 job->request->rqst_data.h_vendor.vendor_cmd;
1768 link_flags = loopback_mode->type;
1769 timeout = loopback_mode->timeout * 100;
1770
1771 rc = lpfc_sli4_bsg_set_link_diag_state(phba, 1);
1772 if (rc)
1773 goto loopback_mode_exit;
1774
1775 /* wait for link down before proceeding */
1776 i = 0;
1777 while (phba->link_state != LPFC_LINK_DOWN) {
1778 if (i++ > timeout) {
1779 rc = -ETIMEDOUT;
1780 goto loopback_mode_exit;
1781 }
1782 msleep(10);
1783 }
1784 /* set up loopback mode */
1785 pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
1786 if (!pmboxq) {
1787 rc = -ENOMEM;
1788 goto loopback_mode_exit;
1789 }
1790 req_len = (sizeof(struct lpfc_mbx_set_link_diag_loopback) -
1791 sizeof(struct lpfc_sli4_cfg_mhdr));
1792 alloc_len = lpfc_sli4_config(phba, pmboxq, LPFC_MBOX_SUBSYSTEM_FCOE,
1793 LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_LOOPBACK,
1794 req_len, LPFC_SLI4_MBX_EMBED);
1795 if (alloc_len != req_len) {
1796 rc = -ENOMEM;
1797 goto loopback_mode_exit;
1798 }
1799 link_diag_loopback = &pmboxq->u.mqe.un.link_diag_loopback;
1800 bf_set(lpfc_mbx_set_diag_state_link_num,
1801 &link_diag_loopback->u.req, phba->sli4_hba.link_state.number);
1802 bf_set(lpfc_mbx_set_diag_state_link_type,
1803 &link_diag_loopback->u.req, phba->sli4_hba.link_state.type);
1804 if (link_flags == INTERNAL_LOOP_BACK)
1805 bf_set(lpfc_mbx_set_diag_lpbk_type,
1806 &link_diag_loopback->u.req,
1807 LPFC_DIAG_LOOPBACK_TYPE_INTERNAL);
1808 else
1809 bf_set(lpfc_mbx_set_diag_lpbk_type,
1810 &link_diag_loopback->u.req,
1811 LPFC_DIAG_LOOPBACK_TYPE_EXTERNAL);
1812
1813 mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, LPFC_MBOX_TMO);
1814 if ((mbxstatus != MBX_SUCCESS) || (pmboxq->u.mb.mbxStatus))
1815 rc = -ENODEV;
1816 else {
1817 phba->link_flag |= LS_LOOPBACK_MODE;
1818 /* wait for the link attention interrupt */
1819 msleep(100);
1820 i = 0;
1821 while (phba->link_state != LPFC_HBA_READY) {
1822 if (i++ > timeout) {
1823 rc = -ETIMEDOUT;
1824 break;
1825 }
1826 msleep(10);
1608 } 1827 }
1609 lpfc_destroy_vport_work_array(phba, vports);
1610 } else {
1611 shost = lpfc_shost_from_vport(phba->pport);
1612 scsi_unblock_requests(shost);
1613 } 1828 }
1614 1829
1830loopback_mode_exit:
1831 lpfc_bsg_diag_mode_exit(phba);
1832
1615 /* 1833 /*
1616 * Let SLI layer release mboxq if mbox command completed after timeout. 1834 * Let SLI layer release mboxq if mbox command completed after timeout.
1617 */ 1835 */
1618 if (mbxstatus != MBX_TIMEOUT) 1836 if (pmboxq && (mbxstatus != MBX_TIMEOUT))
1837 mempool_free(pmboxq, phba->mbox_mem_pool);
1838
1839job_error:
1840 /* make error code available to userspace */
1841 job->reply->result = rc;
1842 /* complete the job back to userspace if no error */
1843 if (rc == 0)
1844 job->job_done(job);
1845 return rc;
1846}
1847
1848/**
1849 * lpfc_bsg_diag_loopback_mode - bsg vendor command for diag loopback mode
1850 * @job: LPFC_BSG_VENDOR_DIAG_MODE
1851 *
1852 * This function is responsible for responding to check and dispatch bsg diag
1853 * command from the user to proper driver action routines.
1854 */
1855static int
1856lpfc_bsg_diag_loopback_mode(struct fc_bsg_job *job)
1857{
1858 struct Scsi_Host *shost;
1859 struct lpfc_vport *vport;
1860 struct lpfc_hba *phba;
1861 int rc;
1862
1863 shost = job->shost;
1864 if (!shost)
1865 return -ENODEV;
1866 vport = (struct lpfc_vport *)job->shost->hostdata;
1867 if (!vport)
1868 return -ENODEV;
1869 phba = vport->phba;
1870 if (!phba)
1871 return -ENODEV;
1872
1873 if (phba->sli_rev < LPFC_SLI_REV4)
1874 rc = lpfc_sli3_bsg_diag_loopback_mode(phba, job);
1875 else if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) ==
1876 LPFC_SLI_INTF_IF_TYPE_2)
1877 rc = lpfc_sli4_bsg_diag_loopback_mode(phba, job);
1878 else
1879 rc = -ENODEV;
1880
1881 return rc;
1882
1883}
1884
1885/**
1886 * lpfc_sli4_bsg_diag_mode_end - sli4 bsg vendor command for ending diag mode
1887 * @job: LPFC_BSG_VENDOR_DIAG_MODE_END
1888 *
1889 * This function is responsible for responding to check and dispatch bsg diag
1890 * command from the user to proper driver action routines.
1891 */
1892static int
1893lpfc_sli4_bsg_diag_mode_end(struct fc_bsg_job *job)
1894{
1895 struct Scsi_Host *shost;
1896 struct lpfc_vport *vport;
1897 struct lpfc_hba *phba;
1898 int rc;
1899
1900 shost = job->shost;
1901 if (!shost)
1902 return -ENODEV;
1903 vport = (struct lpfc_vport *)job->shost->hostdata;
1904 if (!vport)
1905 return -ENODEV;
1906 phba = vport->phba;
1907 if (!phba)
1908 return -ENODEV;
1909
1910 if (phba->sli_rev < LPFC_SLI_REV4)
1911 return -ENODEV;
1912 if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) !=
1913 LPFC_SLI_INTF_IF_TYPE_2)
1914 return -ENODEV;
1915
1916 rc = lpfc_sli4_bsg_set_link_diag_state(phba, 0);
1917
1918 if (!rc)
1919 rc = phba->lpfc_hba_init_link(phba, MBX_NOWAIT);
1920
1921 return rc;
1922}
1923
1924/**
1925 * lpfc_sli4_bsg_link_diag_test - sli4 bsg vendor command for diag link test
1926 * @job: LPFC_BSG_VENDOR_DIAG_LINK_TEST
1927 *
1928 * This function is to perform SLI4 diag link test request from the user
1929 * applicaiton.
1930 */
1931static int
1932lpfc_sli4_bsg_link_diag_test(struct fc_bsg_job *job)
1933{
1934 struct Scsi_Host *shost;
1935 struct lpfc_vport *vport;
1936 struct lpfc_hba *phba;
1937 LPFC_MBOXQ_t *pmboxq;
1938 struct sli4_link_diag *link_diag_test_cmd;
1939 uint32_t req_len, alloc_len;
1940 uint32_t timeout;
1941 struct lpfc_mbx_run_link_diag_test *run_link_diag_test;
1942 union lpfc_sli4_cfg_shdr *shdr;
1943 uint32_t shdr_status, shdr_add_status;
1944 struct diag_status *diag_status_reply;
1945 int mbxstatus, rc = 0;
1946
1947 shost = job->shost;
1948 if (!shost) {
1949 rc = -ENODEV;
1950 goto job_error;
1951 }
1952 vport = (struct lpfc_vport *)job->shost->hostdata;
1953 if (!vport) {
1954 rc = -ENODEV;
1955 goto job_error;
1956 }
1957 phba = vport->phba;
1958 if (!phba) {
1959 rc = -ENODEV;
1960 goto job_error;
1961 }
1962
1963 if (phba->sli_rev < LPFC_SLI_REV4) {
1964 rc = -ENODEV;
1965 goto job_error;
1966 }
1967 if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) !=
1968 LPFC_SLI_INTF_IF_TYPE_2) {
1969 rc = -ENODEV;
1970 goto job_error;
1971 }
1972
1973 if (job->request_len < sizeof(struct fc_bsg_request) +
1974 sizeof(struct sli4_link_diag)) {
1975 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
1976 "3013 Received LINK DIAG TEST request "
1977 " size:%d below the minimum size:%d\n",
1978 job->request_len,
1979 (int)(sizeof(struct fc_bsg_request) +
1980 sizeof(struct sli4_link_diag)));
1981 rc = -EINVAL;
1982 goto job_error;
1983 }
1984
1985 rc = lpfc_bsg_diag_mode_enter(phba, job);
1986 if (rc)
1987 goto job_error;
1988
1989 link_diag_test_cmd = (struct sli4_link_diag *)
1990 job->request->rqst_data.h_vendor.vendor_cmd;
1991 timeout = link_diag_test_cmd->timeout * 100;
1992
1993 rc = lpfc_sli4_bsg_set_link_diag_state(phba, 1);
1994
1995 if (rc)
1996 goto job_error;
1997
1998 pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
1999 if (!pmboxq) {
2000 rc = -ENOMEM;
2001 goto link_diag_test_exit;
2002 }
2003
2004 req_len = (sizeof(struct lpfc_mbx_set_link_diag_state) -
2005 sizeof(struct lpfc_sli4_cfg_mhdr));
2006 alloc_len = lpfc_sli4_config(phba, pmboxq, LPFC_MBOX_SUBSYSTEM_FCOE,
2007 LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_STATE,
2008 req_len, LPFC_SLI4_MBX_EMBED);
2009 if (alloc_len != req_len) {
2010 rc = -ENOMEM;
2011 goto link_diag_test_exit;
2012 }
2013 run_link_diag_test = &pmboxq->u.mqe.un.link_diag_test;
2014 bf_set(lpfc_mbx_run_diag_test_link_num, &run_link_diag_test->u.req,
2015 phba->sli4_hba.link_state.number);
2016 bf_set(lpfc_mbx_run_diag_test_link_type, &run_link_diag_test->u.req,
2017 phba->sli4_hba.link_state.type);
2018 bf_set(lpfc_mbx_run_diag_test_test_id, &run_link_diag_test->u.req,
2019 link_diag_test_cmd->test_id);
2020 bf_set(lpfc_mbx_run_diag_test_loops, &run_link_diag_test->u.req,
2021 link_diag_test_cmd->loops);
2022 bf_set(lpfc_mbx_run_diag_test_test_ver, &run_link_diag_test->u.req,
2023 link_diag_test_cmd->test_version);
2024 bf_set(lpfc_mbx_run_diag_test_err_act, &run_link_diag_test->u.req,
2025 link_diag_test_cmd->error_action);
2026
2027 mbxstatus = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
2028
2029 shdr = (union lpfc_sli4_cfg_shdr *)
2030 &pmboxq->u.mqe.un.sli4_config.header.cfg_shdr;
2031 shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
2032 shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
2033 if (shdr_status || shdr_add_status || mbxstatus) {
2034 lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
2035 "3010 Run link diag test mailbox failed with "
2036 "mbx_status x%x status x%x, add_status x%x\n",
2037 mbxstatus, shdr_status, shdr_add_status);
2038 }
2039
2040 diag_status_reply = (struct diag_status *)
2041 job->reply->reply_data.vendor_reply.vendor_rsp;
2042
2043 if (job->reply_len <
2044 sizeof(struct fc_bsg_request) + sizeof(struct diag_status)) {
2045 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
2046 "3012 Received Run link diag test reply "
2047 "below minimum size (%d): reply_len:%d\n",
2048 (int)(sizeof(struct fc_bsg_request) +
2049 sizeof(struct diag_status)),
2050 job->reply_len);
2051 rc = -EINVAL;
2052 goto job_error;
2053 }
2054
2055 diag_status_reply->mbox_status = mbxstatus;
2056 diag_status_reply->shdr_status = shdr_status;
2057 diag_status_reply->shdr_add_status = shdr_add_status;
2058
2059link_diag_test_exit:
2060 rc = lpfc_sli4_bsg_set_link_diag_state(phba, 0);
2061
2062 if (pmboxq)
1619 mempool_free(pmboxq, phba->mbox_mem_pool); 2063 mempool_free(pmboxq, phba->mbox_mem_pool);
1620 2064
2065 lpfc_bsg_diag_mode_exit(phba);
2066
1621job_error: 2067job_error:
1622 /* make error code available to userspace */ 2068 /* make error code available to userspace */
1623 job->reply->result = rc; 2069 job->reply->result = rc;
@@ -1857,6 +2303,86 @@ err_get_xri_exit:
1857} 2303}
1858 2304
1859/** 2305/**
2306 * lpfc_bsg_dma_page_alloc - allocate a bsg mbox page sized dma buffers
2307 * @phba: Pointer to HBA context object
2308 *
2309 * This function allocates BSG_MBOX_SIZE (4KB) page size dma buffer and.
2310 * retruns the pointer to the buffer.
2311 **/
2312static struct lpfc_dmabuf *
2313lpfc_bsg_dma_page_alloc(struct lpfc_hba *phba)
2314{
2315 struct lpfc_dmabuf *dmabuf;
2316 struct pci_dev *pcidev = phba->pcidev;
2317
2318 /* allocate dma buffer struct */
2319 dmabuf = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
2320 if (!dmabuf)
2321 return NULL;
2322
2323 INIT_LIST_HEAD(&dmabuf->list);
2324
2325 /* now, allocate dma buffer */
2326 dmabuf->virt = dma_alloc_coherent(&pcidev->dev, BSG_MBOX_SIZE,
2327 &(dmabuf->phys), GFP_KERNEL);
2328
2329 if (!dmabuf->virt) {
2330 kfree(dmabuf);
2331 return NULL;
2332 }
2333 memset((uint8_t *)dmabuf->virt, 0, BSG_MBOX_SIZE);
2334
2335 return dmabuf;
2336}
2337
2338/**
2339 * lpfc_bsg_dma_page_free - free a bsg mbox page sized dma buffer
2340 * @phba: Pointer to HBA context object.
2341 * @dmabuf: Pointer to the bsg mbox page sized dma buffer descriptor.
2342 *
2343 * This routine just simply frees a dma buffer and its associated buffer
2344 * descriptor referred by @dmabuf.
2345 **/
2346static void
2347lpfc_bsg_dma_page_free(struct lpfc_hba *phba, struct lpfc_dmabuf *dmabuf)
2348{
2349 struct pci_dev *pcidev = phba->pcidev;
2350
2351 if (!dmabuf)
2352 return;
2353
2354 if (dmabuf->virt)
2355 dma_free_coherent(&pcidev->dev, BSG_MBOX_SIZE,
2356 dmabuf->virt, dmabuf->phys);
2357 kfree(dmabuf);
2358 return;
2359}
2360
2361/**
2362 * lpfc_bsg_dma_page_list_free - free a list of bsg mbox page sized dma buffers
2363 * @phba: Pointer to HBA context object.
2364 * @dmabuf_list: Pointer to a list of bsg mbox page sized dma buffer descs.
2365 *
2366 * This routine just simply frees all dma buffers and their associated buffer
2367 * descriptors referred by @dmabuf_list.
2368 **/
2369static void
2370lpfc_bsg_dma_page_list_free(struct lpfc_hba *phba,
2371 struct list_head *dmabuf_list)
2372{
2373 struct lpfc_dmabuf *dmabuf, *next_dmabuf;
2374
2375 if (list_empty(dmabuf_list))
2376 return;
2377
2378 list_for_each_entry_safe(dmabuf, next_dmabuf, dmabuf_list, list) {
2379 list_del_init(&dmabuf->list);
2380 lpfc_bsg_dma_page_free(phba, dmabuf);
2381 }
2382 return;
2383}
2384
2385/**
1860 * diag_cmd_data_alloc - fills in a bde struct with dma buffers 2386 * diag_cmd_data_alloc - fills in a bde struct with dma buffers
1861 * @phba: Pointer to HBA context object 2387 * @phba: Pointer to HBA context object
1862 * @bpl: Pointer to 64 bit bde structure 2388 * @bpl: Pointer to 64 bit bde structure
@@ -2073,7 +2599,7 @@ err_post_rxbufs_exit:
2073} 2599}
2074 2600
2075/** 2601/**
2076 * lpfc_bsg_diag_test - with a port in loopback issues a Ct cmd to itself 2602 * lpfc_bsg_diag_loopback_run - run loopback on a port by issue ct cmd to itself
2077 * @job: LPFC_BSG_VENDOR_DIAG_TEST fc_bsg_job 2603 * @job: LPFC_BSG_VENDOR_DIAG_TEST fc_bsg_job
2078 * 2604 *
2079 * This function receives a user data buffer to be transmitted and received on 2605 * This function receives a user data buffer to be transmitted and received on
@@ -2092,7 +2618,7 @@ err_post_rxbufs_exit:
2092 * of loopback mode. 2618 * of loopback mode.
2093 **/ 2619 **/
2094static int 2620static int
2095lpfc_bsg_diag_test(struct fc_bsg_job *job) 2621lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job)
2096{ 2622{
2097 struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata; 2623 struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata;
2098 struct lpfc_hba *phba = vport->phba; 2624 struct lpfc_hba *phba = vport->phba;
@@ -2417,7 +2943,7 @@ job_error:
2417} 2943}
2418 2944
2419/** 2945/**
2420 * lpfc_bsg_wake_mbox_wait - lpfc_bsg_issue_mbox mbox completion handler 2946 * lpfc_bsg_issue_mbox_cmpl - lpfc_bsg_issue_mbox mbox completion handler
2421 * @phba: Pointer to HBA context object. 2947 * @phba: Pointer to HBA context object.
2422 * @pmboxq: Pointer to mailbox command. 2948 * @pmboxq: Pointer to mailbox command.
2423 * 2949 *
@@ -2428,15 +2954,13 @@ job_error:
2428 * of the mailbox. 2954 * of the mailbox.
2429 **/ 2955 **/
2430void 2956void
2431lpfc_bsg_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) 2957lpfc_bsg_issue_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
2432{ 2958{
2433 struct bsg_job_data *dd_data; 2959 struct bsg_job_data *dd_data;
2434 struct fc_bsg_job *job; 2960 struct fc_bsg_job *job;
2435 struct lpfc_mbx_nembed_cmd *nembed_sge;
2436 uint32_t size; 2961 uint32_t size;
2437 unsigned long flags; 2962 unsigned long flags;
2438 uint8_t *to; 2963 uint8_t *pmb, *pmb_buf;
2439 uint8_t *from;
2440 2964
2441 spin_lock_irqsave(&phba->ct_ev_lock, flags); 2965 spin_lock_irqsave(&phba->ct_ev_lock, flags);
2442 dd_data = pmboxq->context1; 2966 dd_data = pmboxq->context1;
@@ -2446,62 +2970,21 @@ lpfc_bsg_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
2446 return; 2970 return;
2447 } 2971 }
2448 2972
2449 /* build the outgoing buffer to do an sg copy 2973 /*
2450 * the format is the response mailbox followed by any extended 2974 * The outgoing buffer is readily referred from the dma buffer,
2451 * mailbox data 2975 * just need to get header part from mailboxq structure.
2452 */ 2976 */
2453 from = (uint8_t *)&pmboxq->u.mb; 2977 pmb = (uint8_t *)&pmboxq->u.mb;
2454 to = (uint8_t *)dd_data->context_un.mbox.mb; 2978 pmb_buf = (uint8_t *)dd_data->context_un.mbox.mb;
2455 memcpy(to, from, sizeof(MAILBOX_t)); 2979 memcpy(pmb_buf, pmb, sizeof(MAILBOX_t));
2456 if (pmboxq->u.mb.mbxStatus == MBX_SUCCESS) {
2457 /* copy the extended data if any, count is in words */
2458 if (dd_data->context_un.mbox.outExtWLen) {
2459 from = (uint8_t *)dd_data->context_un.mbox.ext;
2460 to += sizeof(MAILBOX_t);
2461 size = dd_data->context_un.mbox.outExtWLen *
2462 sizeof(uint32_t);
2463 memcpy(to, from, size);
2464 } else if (pmboxq->u.mb.mbxCommand == MBX_RUN_BIU_DIAG64) {
2465 from = (uint8_t *)dd_data->context_un.mbox.
2466 dmp->dma.virt;
2467 to += sizeof(MAILBOX_t);
2468 size = dd_data->context_un.mbox.dmp->size;
2469 memcpy(to, from, size);
2470 } else if ((phba->sli_rev == LPFC_SLI_REV4) &&
2471 (pmboxq->u.mb.mbxCommand == MBX_DUMP_MEMORY)) {
2472 from = (uint8_t *)dd_data->context_un.mbox.dmp->dma.
2473 virt;
2474 to += sizeof(MAILBOX_t);
2475 size = pmboxq->u.mb.un.varWords[5];
2476 memcpy(to, from, size);
2477 } else if ((phba->sli_rev == LPFC_SLI_REV4) &&
2478 (pmboxq->u.mb.mbxCommand == MBX_SLI4_CONFIG)) {
2479 nembed_sge = (struct lpfc_mbx_nembed_cmd *)
2480 &pmboxq->u.mb.un.varWords[0];
2481
2482 from = (uint8_t *)dd_data->context_un.mbox.dmp->dma.
2483 virt;
2484 to += sizeof(MAILBOX_t);
2485 size = nembed_sge->sge[0].length;
2486 memcpy(to, from, size);
2487 } else if (pmboxq->u.mb.mbxCommand == MBX_READ_EVENT_LOG) {
2488 from = (uint8_t *)dd_data->context_un.
2489 mbox.dmp->dma.virt;
2490 to += sizeof(MAILBOX_t);
2491 size = dd_data->context_un.mbox.dmp->size;
2492 memcpy(to, from, size);
2493 }
2494 }
2495 2980
2496 from = (uint8_t *)dd_data->context_un.mbox.mb;
2497 job = dd_data->context_un.mbox.set_job; 2981 job = dd_data->context_un.mbox.set_job;
2498 if (job) { 2982 if (job) {
2499 size = job->reply_payload.payload_len; 2983 size = job->reply_payload.payload_len;
2500 job->reply->reply_payload_rcv_len = 2984 job->reply->reply_payload_rcv_len =
2501 sg_copy_from_buffer(job->reply_payload.sg_list, 2985 sg_copy_from_buffer(job->reply_payload.sg_list,
2502 job->reply_payload.sg_cnt, 2986 job->reply_payload.sg_cnt,
2503 from, size); 2987 pmb_buf, size);
2504 job->reply->result = 0;
2505 /* need to hold the lock until we set job->dd_data to NULL 2988 /* need to hold the lock until we set job->dd_data to NULL
2506 * to hold off the timeout handler returning to the mid-layer 2989 * to hold off the timeout handler returning to the mid-layer
2507 * while we are still processing the job. 2990 * while we are still processing the job.
@@ -2509,28 +2992,19 @@ lpfc_bsg_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
2509 job->dd_data = NULL; 2992 job->dd_data = NULL;
2510 dd_data->context_un.mbox.set_job = NULL; 2993 dd_data->context_un.mbox.set_job = NULL;
2511 spin_unlock_irqrestore(&phba->ct_ev_lock, flags); 2994 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
2512 job->job_done(job);
2513 } else { 2995 } else {
2514 dd_data->context_un.mbox.set_job = NULL; 2996 dd_data->context_un.mbox.set_job = NULL;
2515 spin_unlock_irqrestore(&phba->ct_ev_lock, flags); 2997 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
2516 } 2998 }
2517 2999
2518 kfree(dd_data->context_un.mbox.mb);
2519 mempool_free(dd_data->context_un.mbox.pmboxq, phba->mbox_mem_pool); 3000 mempool_free(dd_data->context_un.mbox.pmboxq, phba->mbox_mem_pool);
2520 kfree(dd_data->context_un.mbox.ext); 3001 lpfc_bsg_dma_page_free(phba, dd_data->context_un.mbox.dmabuffers);
2521 if (dd_data->context_un.mbox.dmp) {
2522 dma_free_coherent(&phba->pcidev->dev,
2523 dd_data->context_un.mbox.dmp->size,
2524 dd_data->context_un.mbox.dmp->dma.virt,
2525 dd_data->context_un.mbox.dmp->dma.phys);
2526 kfree(dd_data->context_un.mbox.dmp);
2527 }
2528 if (dd_data->context_un.mbox.rxbmp) {
2529 lpfc_mbuf_free(phba, dd_data->context_un.mbox.rxbmp->virt,
2530 dd_data->context_un.mbox.rxbmp->phys);
2531 kfree(dd_data->context_un.mbox.rxbmp);
2532 }
2533 kfree(dd_data); 3002 kfree(dd_data);
3003
3004 if (job) {
3005 job->reply->result = 0;
3006 job->job_done(job);
3007 }
2534 return; 3008 return;
2535} 3009}
2536 3010
@@ -2625,6 +3099,1006 @@ static int lpfc_bsg_check_cmd_access(struct lpfc_hba *phba,
2625} 3099}
2626 3100
2627/** 3101/**
3102 * lpfc_bsg_mbox_ext_cleanup - clean up context of multi-buffer mbox session
3103 * @phba: Pointer to HBA context object.
3104 *
3105 * This is routine clean up and reset BSG handling of multi-buffer mbox
3106 * command session.
3107 **/
3108static void
3109lpfc_bsg_mbox_ext_session_reset(struct lpfc_hba *phba)
3110{
3111 if (phba->mbox_ext_buf_ctx.state == LPFC_BSG_MBOX_IDLE)
3112 return;
3113
3114 /* free all memory, including dma buffers */
3115 lpfc_bsg_dma_page_list_free(phba,
3116 &phba->mbox_ext_buf_ctx.ext_dmabuf_list);
3117 lpfc_bsg_dma_page_free(phba, phba->mbox_ext_buf_ctx.mbx_dmabuf);
3118 /* multi-buffer write mailbox command pass-through complete */
3119 memset((char *)&phba->mbox_ext_buf_ctx, 0,
3120 sizeof(struct lpfc_mbox_ext_buf_ctx));
3121 INIT_LIST_HEAD(&phba->mbox_ext_buf_ctx.ext_dmabuf_list);
3122
3123 return;
3124}
3125
3126/**
3127 * lpfc_bsg_issue_mbox_ext_handle_job - job handler for multi-buffer mbox cmpl
3128 * @phba: Pointer to HBA context object.
3129 * @pmboxq: Pointer to mailbox command.
3130 *
3131 * This is routine handles BSG job for mailbox commands completions with
3132 * multiple external buffers.
3133 **/
3134static struct fc_bsg_job *
3135lpfc_bsg_issue_mbox_ext_handle_job(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
3136{
3137 struct bsg_job_data *dd_data;
3138 struct fc_bsg_job *job;
3139 uint8_t *pmb, *pmb_buf;
3140 unsigned long flags;
3141 uint32_t size;
3142 int rc = 0;
3143
3144 spin_lock_irqsave(&phba->ct_ev_lock, flags);
3145 dd_data = pmboxq->context1;
3146 /* has the job already timed out? */
3147 if (!dd_data) {
3148 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
3149 job = NULL;
3150 goto job_done_out;
3151 }
3152
3153 /*
3154 * The outgoing buffer is readily referred from the dma buffer,
3155 * just need to get header part from mailboxq structure.
3156 */
3157 pmb = (uint8_t *)&pmboxq->u.mb;
3158 pmb_buf = (uint8_t *)dd_data->context_un.mbox.mb;
3159 memcpy(pmb_buf, pmb, sizeof(MAILBOX_t));
3160
3161 job = dd_data->context_un.mbox.set_job;
3162 if (job) {
3163 size = job->reply_payload.payload_len;
3164 job->reply->reply_payload_rcv_len =
3165 sg_copy_from_buffer(job->reply_payload.sg_list,
3166 job->reply_payload.sg_cnt,
3167 pmb_buf, size);
3168 /* result for successful */
3169 job->reply->result = 0;
3170 job->dd_data = NULL;
3171 /* need to hold the lock util we set job->dd_data to NULL
3172 * to hold off the timeout handler from midlayer to take
3173 * any action.
3174 */
3175 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
3176 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3177 "2937 SLI_CONFIG ext-buffer maibox command "
3178 "(x%x/x%x) complete bsg job done, bsize:%d\n",
3179 phba->mbox_ext_buf_ctx.nembType,
3180 phba->mbox_ext_buf_ctx.mboxType, size);
3181 } else
3182 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
3183
3184job_done_out:
3185 if (!job)
3186 lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
3187 "2938 SLI_CONFIG ext-buffer maibox "
3188 "command (x%x/x%x) failure, rc:x%x\n",
3189 phba->mbox_ext_buf_ctx.nembType,
3190 phba->mbox_ext_buf_ctx.mboxType, rc);
3191 /* state change */
3192 phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_DONE;
3193 kfree(dd_data);
3194
3195 return job;
3196}
3197
3198/**
3199 * lpfc_bsg_issue_read_mbox_ext_cmpl - compl handler for multi-buffer read mbox
3200 * @phba: Pointer to HBA context object.
3201 * @pmboxq: Pointer to mailbox command.
3202 *
3203 * This is completion handler function for mailbox read commands with multiple
3204 * external buffers.
3205 **/
3206static void
3207lpfc_bsg_issue_read_mbox_ext_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
3208{
3209 struct fc_bsg_job *job;
3210
3211 /* handle the BSG job with mailbox command */
3212 if (phba->mbox_ext_buf_ctx.state == LPFC_BSG_MBOX_ABTS)
3213 pmboxq->u.mb.mbxStatus = MBXERR_ERROR;
3214
3215 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3216 "2939 SLI_CONFIG ext-buffer rd maibox command "
3217 "complete, ctxState:x%x, mbxStatus:x%x\n",
3218 phba->mbox_ext_buf_ctx.state, pmboxq->u.mb.mbxStatus);
3219
3220 job = lpfc_bsg_issue_mbox_ext_handle_job(phba, pmboxq);
3221
3222 if (pmboxq->u.mb.mbxStatus || phba->mbox_ext_buf_ctx.numBuf == 1)
3223 lpfc_bsg_mbox_ext_session_reset(phba);
3224
3225 /* free base driver mailbox structure memory */
3226 mempool_free(pmboxq, phba->mbox_mem_pool);
3227
3228 /* complete the bsg job if we have it */
3229 if (job)
3230 job->job_done(job);
3231
3232 return;
3233}
3234
3235/**
3236 * lpfc_bsg_issue_write_mbox_ext_cmpl - cmpl handler for multi-buffer write mbox
3237 * @phba: Pointer to HBA context object.
3238 * @pmboxq: Pointer to mailbox command.
3239 *
3240 * This is completion handler function for mailbox write commands with multiple
3241 * external buffers.
3242 **/
3243static void
3244lpfc_bsg_issue_write_mbox_ext_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
3245{
3246 struct fc_bsg_job *job;
3247
3248 /* handle the BSG job with the mailbox command */
3249 if (phba->mbox_ext_buf_ctx.state == LPFC_BSG_MBOX_ABTS)
3250 pmboxq->u.mb.mbxStatus = MBXERR_ERROR;
3251
3252 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3253 "2940 SLI_CONFIG ext-buffer wr maibox command "
3254 "complete, ctxState:x%x, mbxStatus:x%x\n",
3255 phba->mbox_ext_buf_ctx.state, pmboxq->u.mb.mbxStatus);
3256
3257 job = lpfc_bsg_issue_mbox_ext_handle_job(phba, pmboxq);
3258
3259 /* free all memory, including dma buffers */
3260 mempool_free(pmboxq, phba->mbox_mem_pool);
3261 lpfc_bsg_mbox_ext_session_reset(phba);
3262
3263 /* complete the bsg job if we have it */
3264 if (job)
3265 job->job_done(job);
3266
3267 return;
3268}
3269
3270static void
3271lpfc_bsg_sli_cfg_dma_desc_setup(struct lpfc_hba *phba, enum nemb_type nemb_tp,
3272 uint32_t index, struct lpfc_dmabuf *mbx_dmabuf,
3273 struct lpfc_dmabuf *ext_dmabuf)
3274{
3275 struct lpfc_sli_config_mbox *sli_cfg_mbx;
3276
3277 /* pointer to the start of mailbox command */
3278 sli_cfg_mbx = (struct lpfc_sli_config_mbox *)mbx_dmabuf->virt;
3279
3280 if (nemb_tp == nemb_mse) {
3281 if (index == 0) {
3282 sli_cfg_mbx->un.sli_config_emb0_subsys.
3283 mse[index].pa_hi =
3284 putPaddrHigh(mbx_dmabuf->phys +
3285 sizeof(MAILBOX_t));
3286 sli_cfg_mbx->un.sli_config_emb0_subsys.
3287 mse[index].pa_lo =
3288 putPaddrLow(mbx_dmabuf->phys +
3289 sizeof(MAILBOX_t));
3290 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3291 "2943 SLI_CONFIG(mse)[%d], "
3292 "bufLen:%d, addrHi:x%x, addrLo:x%x\n",
3293 index,
3294 sli_cfg_mbx->un.sli_config_emb0_subsys.
3295 mse[index].buf_len,
3296 sli_cfg_mbx->un.sli_config_emb0_subsys.
3297 mse[index].pa_hi,
3298 sli_cfg_mbx->un.sli_config_emb0_subsys.
3299 mse[index].pa_lo);
3300 } else {
3301 sli_cfg_mbx->un.sli_config_emb0_subsys.
3302 mse[index].pa_hi =
3303 putPaddrHigh(ext_dmabuf->phys);
3304 sli_cfg_mbx->un.sli_config_emb0_subsys.
3305 mse[index].pa_lo =
3306 putPaddrLow(ext_dmabuf->phys);
3307 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3308 "2944 SLI_CONFIG(mse)[%d], "
3309 "bufLen:%d, addrHi:x%x, addrLo:x%x\n",
3310 index,
3311 sli_cfg_mbx->un.sli_config_emb0_subsys.
3312 mse[index].buf_len,
3313 sli_cfg_mbx->un.sli_config_emb0_subsys.
3314 mse[index].pa_hi,
3315 sli_cfg_mbx->un.sli_config_emb0_subsys.
3316 mse[index].pa_lo);
3317 }
3318 } else {
3319 if (index == 0) {
3320 sli_cfg_mbx->un.sli_config_emb1_subsys.
3321 hbd[index].pa_hi =
3322 putPaddrHigh(mbx_dmabuf->phys +
3323 sizeof(MAILBOX_t));
3324 sli_cfg_mbx->un.sli_config_emb1_subsys.
3325 hbd[index].pa_lo =
3326 putPaddrLow(mbx_dmabuf->phys +
3327 sizeof(MAILBOX_t));
3328 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3329 "3007 SLI_CONFIG(hbd)[%d], "
3330 "bufLen:%d, addrHi:x%x, addrLo:x%x\n",
3331 index,
3332 bsg_bf_get(lpfc_mbox_sli_config_ecmn_hbd_len,
3333 &sli_cfg_mbx->un.
3334 sli_config_emb1_subsys.hbd[index]),
3335 sli_cfg_mbx->un.sli_config_emb1_subsys.
3336 hbd[index].pa_hi,
3337 sli_cfg_mbx->un.sli_config_emb1_subsys.
3338 hbd[index].pa_lo);
3339
3340 } else {
3341 sli_cfg_mbx->un.sli_config_emb1_subsys.
3342 hbd[index].pa_hi =
3343 putPaddrHigh(ext_dmabuf->phys);
3344 sli_cfg_mbx->un.sli_config_emb1_subsys.
3345 hbd[index].pa_lo =
3346 putPaddrLow(ext_dmabuf->phys);
3347 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3348 "3008 SLI_CONFIG(hbd)[%d], "
3349 "bufLen:%d, addrHi:x%x, addrLo:x%x\n",
3350 index,
3351 bsg_bf_get(lpfc_mbox_sli_config_ecmn_hbd_len,
3352 &sli_cfg_mbx->un.
3353 sli_config_emb1_subsys.hbd[index]),
3354 sli_cfg_mbx->un.sli_config_emb1_subsys.
3355 hbd[index].pa_hi,
3356 sli_cfg_mbx->un.sli_config_emb1_subsys.
3357 hbd[index].pa_lo);
3358 }
3359 }
3360 return;
3361}
3362
3363/**
3364 * lpfc_bsg_sli_cfg_mse_read_cmd_ext - sli_config non-embedded mailbox cmd read
3365 * @phba: Pointer to HBA context object.
3366 * @mb: Pointer to a BSG mailbox object.
3367 * @nemb_tp: Enumerate of non-embedded mailbox command type.
3368 * @dmabuff: Pointer to a DMA buffer descriptor.
3369 *
3370 * This routine performs SLI_CONFIG (0x9B) read mailbox command operation with
3371 * non-embedded external bufffers.
3372 **/
3373static int
3374lpfc_bsg_sli_cfg_read_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job,
3375 enum nemb_type nemb_tp,
3376 struct lpfc_dmabuf *dmabuf)
3377{
3378 struct lpfc_sli_config_mbox *sli_cfg_mbx;
3379 struct dfc_mbox_req *mbox_req;
3380 struct lpfc_dmabuf *curr_dmabuf, *next_dmabuf;
3381 uint32_t ext_buf_cnt, ext_buf_index;
3382 struct lpfc_dmabuf *ext_dmabuf = NULL;
3383 struct bsg_job_data *dd_data = NULL;
3384 LPFC_MBOXQ_t *pmboxq = NULL;
3385 MAILBOX_t *pmb;
3386 uint8_t *pmbx;
3387 int rc, i;
3388
3389 mbox_req =
3390 (struct dfc_mbox_req *)job->request->rqst_data.h_vendor.vendor_cmd;
3391
3392 /* pointer to the start of mailbox command */
3393 sli_cfg_mbx = (struct lpfc_sli_config_mbox *)dmabuf->virt;
3394
3395 if (nemb_tp == nemb_mse) {
3396 ext_buf_cnt = bsg_bf_get(lpfc_mbox_hdr_mse_cnt,
3397 &sli_cfg_mbx->un.sli_config_emb0_subsys.sli_config_hdr);
3398 if (ext_buf_cnt > LPFC_MBX_SLI_CONFIG_MAX_MSE) {
3399 lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
3400 "2945 Handled SLI_CONFIG(mse) rd, "
3401 "ext_buf_cnt(%d) out of range(%d)\n",
3402 ext_buf_cnt,
3403 LPFC_MBX_SLI_CONFIG_MAX_MSE);
3404 rc = -ERANGE;
3405 goto job_error;
3406 }
3407 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3408 "2941 Handled SLI_CONFIG(mse) rd, "
3409 "ext_buf_cnt:%d\n", ext_buf_cnt);
3410 } else {
3411 /* sanity check on interface type for support */
3412 if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) !=
3413 LPFC_SLI_INTF_IF_TYPE_2) {
3414 rc = -ENODEV;
3415 goto job_error;
3416 }
3417 /* nemb_tp == nemb_hbd */
3418 ext_buf_cnt = sli_cfg_mbx->un.sli_config_emb1_subsys.hbd_count;
3419 if (ext_buf_cnt > LPFC_MBX_SLI_CONFIG_MAX_HBD) {
3420 lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
3421 "2946 Handled SLI_CONFIG(hbd) rd, "
3422 "ext_buf_cnt(%d) out of range(%d)\n",
3423 ext_buf_cnt,
3424 LPFC_MBX_SLI_CONFIG_MAX_HBD);
3425 rc = -ERANGE;
3426 goto job_error;
3427 }
3428 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3429 "2942 Handled SLI_CONFIG(hbd) rd, "
3430 "ext_buf_cnt:%d\n", ext_buf_cnt);
3431 }
3432
3433 /* reject non-embedded mailbox command with none external buffer */
3434 if (ext_buf_cnt == 0) {
3435 rc = -EPERM;
3436 goto job_error;
3437 } else if (ext_buf_cnt > 1) {
3438 /* additional external read buffers */
3439 for (i = 1; i < ext_buf_cnt; i++) {
3440 ext_dmabuf = lpfc_bsg_dma_page_alloc(phba);
3441 if (!ext_dmabuf) {
3442 rc = -ENOMEM;
3443 goto job_error;
3444 }
3445 list_add_tail(&ext_dmabuf->list,
3446 &phba->mbox_ext_buf_ctx.ext_dmabuf_list);
3447 }
3448 }
3449
3450 /* bsg tracking structure */
3451 dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);
3452 if (!dd_data) {
3453 rc = -ENOMEM;
3454 goto job_error;
3455 }
3456
3457 /* mailbox command structure for base driver */
3458 pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
3459 if (!pmboxq) {
3460 rc = -ENOMEM;
3461 goto job_error;
3462 }
3463 memset(pmboxq, 0, sizeof(LPFC_MBOXQ_t));
3464
3465 /* for the first external buffer */
3466 lpfc_bsg_sli_cfg_dma_desc_setup(phba, nemb_tp, 0, dmabuf, dmabuf);
3467
3468 /* for the rest of external buffer descriptors if any */
3469 if (ext_buf_cnt > 1) {
3470 ext_buf_index = 1;
3471 list_for_each_entry_safe(curr_dmabuf, next_dmabuf,
3472 &phba->mbox_ext_buf_ctx.ext_dmabuf_list, list) {
3473 lpfc_bsg_sli_cfg_dma_desc_setup(phba, nemb_tp,
3474 ext_buf_index, dmabuf,
3475 curr_dmabuf);
3476 ext_buf_index++;
3477 }
3478 }
3479
3480 /* construct base driver mbox command */
3481 pmb = &pmboxq->u.mb;
3482 pmbx = (uint8_t *)dmabuf->virt;
3483 memcpy(pmb, pmbx, sizeof(*pmb));
3484 pmb->mbxOwner = OWN_HOST;
3485 pmboxq->vport = phba->pport;
3486
3487 /* multi-buffer handling context */
3488 phba->mbox_ext_buf_ctx.nembType = nemb_tp;
3489 phba->mbox_ext_buf_ctx.mboxType = mbox_rd;
3490 phba->mbox_ext_buf_ctx.numBuf = ext_buf_cnt;
3491 phba->mbox_ext_buf_ctx.mbxTag = mbox_req->extMboxTag;
3492 phba->mbox_ext_buf_ctx.seqNum = mbox_req->extSeqNum;
3493 phba->mbox_ext_buf_ctx.mbx_dmabuf = dmabuf;
3494
3495 /* callback for multi-buffer read mailbox command */
3496 pmboxq->mbox_cmpl = lpfc_bsg_issue_read_mbox_ext_cmpl;
3497
3498 /* context fields to callback function */
3499 pmboxq->context1 = dd_data;
3500 dd_data->type = TYPE_MBOX;
3501 dd_data->context_un.mbox.pmboxq = pmboxq;
3502 dd_data->context_un.mbox.mb = (MAILBOX_t *)pmbx;
3503 dd_data->context_un.mbox.set_job = job;
3504 job->dd_data = dd_data;
3505
3506 /* state change */
3507 phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_PORT;
3508
3509 rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT);
3510 if ((rc == MBX_SUCCESS) || (rc == MBX_BUSY)) {
3511 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3512 "2947 Issued SLI_CONFIG ext-buffer "
3513 "maibox command, rc:x%x\n", rc);
3514 return 1;
3515 }
3516 lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
3517 "2948 Failed to issue SLI_CONFIG ext-buffer "
3518 "maibox command, rc:x%x\n", rc);
3519 rc = -EPIPE;
3520
3521job_error:
3522 if (pmboxq)
3523 mempool_free(pmboxq, phba->mbox_mem_pool);
3524 lpfc_bsg_dma_page_list_free(phba,
3525 &phba->mbox_ext_buf_ctx.ext_dmabuf_list);
3526 kfree(dd_data);
3527 phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_IDLE;
3528 return rc;
3529}
3530
3531/**
3532 * lpfc_bsg_sli_cfg_write_cmd_ext - sli_config non-embedded mailbox cmd write
3533 * @phba: Pointer to HBA context object.
3534 * @mb: Pointer to a BSG mailbox object.
3535 * @dmabuff: Pointer to a DMA buffer descriptor.
3536 *
3537 * This routine performs SLI_CONFIG (0x9B) write mailbox command operation with
3538 * non-embedded external bufffers.
3539 **/
3540static int
3541lpfc_bsg_sli_cfg_write_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job,
3542 enum nemb_type nemb_tp,
3543 struct lpfc_dmabuf *dmabuf)
3544{
3545 struct dfc_mbox_req *mbox_req;
3546 struct lpfc_sli_config_mbox *sli_cfg_mbx;
3547 uint32_t ext_buf_cnt;
3548 struct bsg_job_data *dd_data = NULL;
3549 LPFC_MBOXQ_t *pmboxq = NULL;
3550 MAILBOX_t *pmb;
3551 uint8_t *mbx;
3552 int rc = 0, i;
3553
3554 mbox_req =
3555 (struct dfc_mbox_req *)job->request->rqst_data.h_vendor.vendor_cmd;
3556
3557 /* pointer to the start of mailbox command */
3558 sli_cfg_mbx = (struct lpfc_sli_config_mbox *)dmabuf->virt;
3559
3560 if (nemb_tp == nemb_mse) {
3561 ext_buf_cnt = bsg_bf_get(lpfc_mbox_hdr_mse_cnt,
3562 &sli_cfg_mbx->un.sli_config_emb0_subsys.sli_config_hdr);
3563 if (ext_buf_cnt > LPFC_MBX_SLI_CONFIG_MAX_MSE) {
3564 lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
3565 "2953 Handled SLI_CONFIG(mse) wr, "
3566 "ext_buf_cnt(%d) out of range(%d)\n",
3567 ext_buf_cnt,
3568 LPFC_MBX_SLI_CONFIG_MAX_MSE);
3569 return -ERANGE;
3570 }
3571 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3572 "2949 Handled SLI_CONFIG(mse) wr, "
3573 "ext_buf_cnt:%d\n", ext_buf_cnt);
3574 } else {
3575 /* sanity check on interface type for support */
3576 if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) !=
3577 LPFC_SLI_INTF_IF_TYPE_2)
3578 return -ENODEV;
3579 /* nemb_tp == nemb_hbd */
3580 ext_buf_cnt = sli_cfg_mbx->un.sli_config_emb1_subsys.hbd_count;
3581 if (ext_buf_cnt > LPFC_MBX_SLI_CONFIG_MAX_HBD) {
3582 lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
3583 "2954 Handled SLI_CONFIG(hbd) wr, "
3584 "ext_buf_cnt(%d) out of range(%d)\n",
3585 ext_buf_cnt,
3586 LPFC_MBX_SLI_CONFIG_MAX_HBD);
3587 return -ERANGE;
3588 }
3589 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3590 "2950 Handled SLI_CONFIG(hbd) wr, "
3591 "ext_buf_cnt:%d\n", ext_buf_cnt);
3592 }
3593
3594 if (ext_buf_cnt == 0)
3595 return -EPERM;
3596
3597 /* for the first external buffer */
3598 lpfc_bsg_sli_cfg_dma_desc_setup(phba, nemb_tp, 0, dmabuf, dmabuf);
3599
3600 /* log for looking forward */
3601 for (i = 1; i < ext_buf_cnt; i++) {
3602 if (nemb_tp == nemb_mse)
3603 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3604 "2951 SLI_CONFIG(mse), buf[%d]-length:%d\n",
3605 i, sli_cfg_mbx->un.sli_config_emb0_subsys.
3606 mse[i].buf_len);
3607 else
3608 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3609 "2952 SLI_CONFIG(hbd), buf[%d]-length:%d\n",
3610 i, bsg_bf_get(lpfc_mbox_sli_config_ecmn_hbd_len,
3611 &sli_cfg_mbx->un.sli_config_emb1_subsys.
3612 hbd[i]));
3613 }
3614
3615 /* multi-buffer handling context */
3616 phba->mbox_ext_buf_ctx.nembType = nemb_tp;
3617 phba->mbox_ext_buf_ctx.mboxType = mbox_wr;
3618 phba->mbox_ext_buf_ctx.numBuf = ext_buf_cnt;
3619 phba->mbox_ext_buf_ctx.mbxTag = mbox_req->extMboxTag;
3620 phba->mbox_ext_buf_ctx.seqNum = mbox_req->extSeqNum;
3621 phba->mbox_ext_buf_ctx.mbx_dmabuf = dmabuf;
3622
3623 if (ext_buf_cnt == 1) {
3624 /* bsg tracking structure */
3625 dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);
3626 if (!dd_data) {
3627 rc = -ENOMEM;
3628 goto job_error;
3629 }
3630
3631 /* mailbox command structure for base driver */
3632 pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
3633 if (!pmboxq) {
3634 rc = -ENOMEM;
3635 goto job_error;
3636 }
3637 memset(pmboxq, 0, sizeof(LPFC_MBOXQ_t));
3638 pmb = &pmboxq->u.mb;
3639 mbx = (uint8_t *)dmabuf->virt;
3640 memcpy(pmb, mbx, sizeof(*pmb));
3641 pmb->mbxOwner = OWN_HOST;
3642 pmboxq->vport = phba->pport;
3643
3644 /* callback for multi-buffer read mailbox command */
3645 pmboxq->mbox_cmpl = lpfc_bsg_issue_write_mbox_ext_cmpl;
3646
3647 /* context fields to callback function */
3648 pmboxq->context1 = dd_data;
3649 dd_data->type = TYPE_MBOX;
3650 dd_data->context_un.mbox.pmboxq = pmboxq;
3651 dd_data->context_un.mbox.mb = (MAILBOX_t *)mbx;
3652 dd_data->context_un.mbox.set_job = job;
3653 job->dd_data = dd_data;
3654
3655 /* state change */
3656 phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_PORT;
3657
3658 rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT);
3659 if ((rc == MBX_SUCCESS) || (rc == MBX_BUSY)) {
3660 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3661 "2955 Issued SLI_CONFIG ext-buffer "
3662 "maibox command, rc:x%x\n", rc);
3663 return 1;
3664 }
3665 lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
3666 "2956 Failed to issue SLI_CONFIG ext-buffer "
3667 "maibox command, rc:x%x\n", rc);
3668 rc = -EPIPE;
3669 }
3670
3671job_error:
3672 if (pmboxq)
3673 mempool_free(pmboxq, phba->mbox_mem_pool);
3674 kfree(dd_data);
3675
3676 return rc;
3677}
3678
3679/**
3680 * lpfc_bsg_handle_sli_cfg_mbox - handle sli-cfg mailbox cmd with ext buffer
3681 * @phba: Pointer to HBA context object.
3682 * @mb: Pointer to a BSG mailbox object.
3683 * @dmabuff: Pointer to a DMA buffer descriptor.
3684 *
3685 * This routine handles SLI_CONFIG (0x9B) mailbox command with non-embedded
3686 * external bufffers, including both 0x9B with non-embedded MSEs and 0x9B
3687 * with embedded sussystem 0x1 and opcodes with external HBDs.
3688 **/
3689static int
3690lpfc_bsg_handle_sli_cfg_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
3691 struct lpfc_dmabuf *dmabuf)
3692{
3693 struct lpfc_sli_config_mbox *sli_cfg_mbx;
3694 uint32_t subsys;
3695 uint32_t opcode;
3696 int rc = SLI_CONFIG_NOT_HANDLED;
3697
3698 /* state change */
3699 phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_HOST;
3700
3701 sli_cfg_mbx = (struct lpfc_sli_config_mbox *)dmabuf->virt;
3702
3703 if (!bsg_bf_get(lpfc_mbox_hdr_emb,
3704 &sli_cfg_mbx->un.sli_config_emb0_subsys.sli_config_hdr)) {
3705 subsys = bsg_bf_get(lpfc_emb0_subcmnd_subsys,
3706 &sli_cfg_mbx->un.sli_config_emb0_subsys);
3707 opcode = bsg_bf_get(lpfc_emb0_subcmnd_opcode,
3708 &sli_cfg_mbx->un.sli_config_emb0_subsys);
3709 if (subsys == SLI_CONFIG_SUBSYS_FCOE) {
3710 switch (opcode) {
3711 case FCOE_OPCODE_READ_FCF:
3712 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3713 "2957 Handled SLI_CONFIG "
3714 "subsys_fcoe, opcode:x%x\n",
3715 opcode);
3716 rc = lpfc_bsg_sli_cfg_read_cmd_ext(phba, job,
3717 nemb_mse, dmabuf);
3718 break;
3719 case FCOE_OPCODE_ADD_FCF:
3720 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3721 "2958 Handled SLI_CONFIG "
3722 "subsys_fcoe, opcode:x%x\n",
3723 opcode);
3724 rc = lpfc_bsg_sli_cfg_write_cmd_ext(phba, job,
3725 nemb_mse, dmabuf);
3726 break;
3727 default:
3728 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3729 "2959 Not handled SLI_CONFIG "
3730 "subsys_fcoe, opcode:x%x\n",
3731 opcode);
3732 rc = SLI_CONFIG_NOT_HANDLED;
3733 break;
3734 }
3735 } else {
3736 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3737 "2977 Handled SLI_CONFIG "
3738 "subsys:x%d, opcode:x%x\n",
3739 subsys, opcode);
3740 rc = SLI_CONFIG_NOT_HANDLED;
3741 }
3742 } else {
3743 subsys = bsg_bf_get(lpfc_emb1_subcmnd_subsys,
3744 &sli_cfg_mbx->un.sli_config_emb1_subsys);
3745 opcode = bsg_bf_get(lpfc_emb1_subcmnd_opcode,
3746 &sli_cfg_mbx->un.sli_config_emb1_subsys);
3747 if (subsys == SLI_CONFIG_SUBSYS_COMN) {
3748 switch (opcode) {
3749 case COMN_OPCODE_READ_OBJECT:
3750 case COMN_OPCODE_READ_OBJECT_LIST:
3751 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3752 "2960 Handled SLI_CONFIG "
3753 "subsys_comn, opcode:x%x\n",
3754 opcode);
3755 rc = lpfc_bsg_sli_cfg_read_cmd_ext(phba, job,
3756 nemb_hbd, dmabuf);
3757 break;
3758 case COMN_OPCODE_WRITE_OBJECT:
3759 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3760 "2961 Handled SLI_CONFIG "
3761 "subsys_comn, opcode:x%x\n",
3762 opcode);
3763 rc = lpfc_bsg_sli_cfg_write_cmd_ext(phba, job,
3764 nemb_hbd, dmabuf);
3765 break;
3766 default:
3767 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3768 "2962 Not handled SLI_CONFIG "
3769 "subsys_comn, opcode:x%x\n",
3770 opcode);
3771 rc = SLI_CONFIG_NOT_HANDLED;
3772 break;
3773 }
3774 } else {
3775 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3776 "2978 Handled SLI_CONFIG "
3777 "subsys:x%d, opcode:x%x\n",
3778 subsys, opcode);
3779 rc = SLI_CONFIG_NOT_HANDLED;
3780 }
3781 }
3782 return rc;
3783}
3784
3785/**
3786 * lpfc_bsg_mbox_ext_abort_req - request to abort mbox command with ext buffers
3787 * @phba: Pointer to HBA context object.
3788 *
3789 * This routine is for requesting to abort a pass-through mailbox command with
3790 * multiple external buffers due to error condition.
3791 **/
3792static void
3793lpfc_bsg_mbox_ext_abort(struct lpfc_hba *phba)
3794{
3795 if (phba->mbox_ext_buf_ctx.state == LPFC_BSG_MBOX_PORT)
3796 phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_ABTS;
3797 else
3798 lpfc_bsg_mbox_ext_session_reset(phba);
3799 return;
3800}
3801
3802/**
3803 * lpfc_bsg_read_ebuf_get - get the next mailbox read external buffer
3804 * @phba: Pointer to HBA context object.
3805 * @dmabuf: Pointer to a DMA buffer descriptor.
3806 *
3807 * This routine extracts the next mailbox read external buffer back to
3808 * user space through BSG.
3809 **/
3810static int
3811lpfc_bsg_read_ebuf_get(struct lpfc_hba *phba, struct fc_bsg_job *job)
3812{
3813 struct lpfc_sli_config_mbox *sli_cfg_mbx;
3814 struct lpfc_dmabuf *dmabuf;
3815 uint8_t *pbuf;
3816 uint32_t size;
3817 uint32_t index;
3818
3819 index = phba->mbox_ext_buf_ctx.seqNum;
3820 phba->mbox_ext_buf_ctx.seqNum++;
3821
3822 sli_cfg_mbx = (struct lpfc_sli_config_mbox *)
3823 phba->mbox_ext_buf_ctx.mbx_dmabuf->virt;
3824
3825 if (phba->mbox_ext_buf_ctx.nembType == nemb_mse) {
3826 size = bsg_bf_get(lpfc_mbox_sli_config_mse_len,
3827 &sli_cfg_mbx->un.sli_config_emb0_subsys.mse[index]);
3828 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3829 "2963 SLI_CONFIG (mse) ext-buffer rd get "
3830 "buffer[%d], size:%d\n", index, size);
3831 } else {
3832 size = bsg_bf_get(lpfc_mbox_sli_config_ecmn_hbd_len,
3833 &sli_cfg_mbx->un.sli_config_emb1_subsys.hbd[index]);
3834 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3835 "2964 SLI_CONFIG (hbd) ext-buffer rd get "
3836 "buffer[%d], size:%d\n", index, size);
3837 }
3838 if (list_empty(&phba->mbox_ext_buf_ctx.ext_dmabuf_list))
3839 return -EPIPE;
3840 dmabuf = list_first_entry(&phba->mbox_ext_buf_ctx.ext_dmabuf_list,
3841 struct lpfc_dmabuf, list);
3842 list_del_init(&dmabuf->list);
3843 pbuf = (uint8_t *)dmabuf->virt;
3844 job->reply->reply_payload_rcv_len =
3845 sg_copy_from_buffer(job->reply_payload.sg_list,
3846 job->reply_payload.sg_cnt,
3847 pbuf, size);
3848
3849 lpfc_bsg_dma_page_free(phba, dmabuf);
3850
3851 if (phba->mbox_ext_buf_ctx.seqNum == phba->mbox_ext_buf_ctx.numBuf) {
3852 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3853 "2965 SLI_CONFIG (hbd) ext-buffer rd mbox "
3854 "command session done\n");
3855 lpfc_bsg_mbox_ext_session_reset(phba);
3856 }
3857
3858 job->reply->result = 0;
3859 job->job_done(job);
3860
3861 return SLI_CONFIG_HANDLED;
3862}
3863
3864/**
3865 * lpfc_bsg_write_ebuf_set - set the next mailbox write external buffer
3866 * @phba: Pointer to HBA context object.
3867 * @dmabuf: Pointer to a DMA buffer descriptor.
3868 *
3869 * This routine sets up the next mailbox read external buffer obtained
3870 * from user space through BSG.
3871 **/
3872static int
3873lpfc_bsg_write_ebuf_set(struct lpfc_hba *phba, struct fc_bsg_job *job,
3874 struct lpfc_dmabuf *dmabuf)
3875{
3876 struct lpfc_sli_config_mbox *sli_cfg_mbx;
3877 struct bsg_job_data *dd_data = NULL;
3878 LPFC_MBOXQ_t *pmboxq = NULL;
3879 MAILBOX_t *pmb;
3880 enum nemb_type nemb_tp;
3881 uint8_t *pbuf;
3882 uint32_t size;
3883 uint32_t index;
3884 int rc;
3885
3886 index = phba->mbox_ext_buf_ctx.seqNum;
3887 phba->mbox_ext_buf_ctx.seqNum++;
3888 nemb_tp = phba->mbox_ext_buf_ctx.nembType;
3889
3890 sli_cfg_mbx = (struct lpfc_sli_config_mbox *)
3891 phba->mbox_ext_buf_ctx.mbx_dmabuf->virt;
3892
3893 dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);
3894 if (!dd_data) {
3895 rc = -ENOMEM;
3896 goto job_error;
3897 }
3898
3899 pbuf = (uint8_t *)dmabuf->virt;
3900 size = job->request_payload.payload_len;
3901 sg_copy_to_buffer(job->request_payload.sg_list,
3902 job->request_payload.sg_cnt,
3903 pbuf, size);
3904
3905 if (phba->mbox_ext_buf_ctx.nembType == nemb_mse) {
3906 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3907 "2966 SLI_CONFIG (mse) ext-buffer wr set "
3908 "buffer[%d], size:%d\n",
3909 phba->mbox_ext_buf_ctx.seqNum, size);
3910
3911 } else {
3912 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3913 "2967 SLI_CONFIG (hbd) ext-buffer wr set "
3914 "buffer[%d], size:%d\n",
3915 phba->mbox_ext_buf_ctx.seqNum, size);
3916
3917 }
3918
3919 /* set up external buffer descriptor and add to external buffer list */
3920 lpfc_bsg_sli_cfg_dma_desc_setup(phba, nemb_tp, index,
3921 phba->mbox_ext_buf_ctx.mbx_dmabuf,
3922 dmabuf);
3923 list_add_tail(&dmabuf->list, &phba->mbox_ext_buf_ctx.ext_dmabuf_list);
3924
3925 if (phba->mbox_ext_buf_ctx.seqNum == phba->mbox_ext_buf_ctx.numBuf) {
3926 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3927 "2968 SLI_CONFIG ext-buffer wr all %d "
3928 "ebuffers received\n",
3929 phba->mbox_ext_buf_ctx.numBuf);
3930 /* mailbox command structure for base driver */
3931 pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
3932 if (!pmboxq) {
3933 rc = -ENOMEM;
3934 goto job_error;
3935 }
3936 memset(pmboxq, 0, sizeof(LPFC_MBOXQ_t));
3937 pbuf = (uint8_t *)phba->mbox_ext_buf_ctx.mbx_dmabuf->virt;
3938 pmb = &pmboxq->u.mb;
3939 memcpy(pmb, pbuf, sizeof(*pmb));
3940 pmb->mbxOwner = OWN_HOST;
3941 pmboxq->vport = phba->pport;
3942
3943 /* callback for multi-buffer write mailbox command */
3944 pmboxq->mbox_cmpl = lpfc_bsg_issue_write_mbox_ext_cmpl;
3945
3946 /* context fields to callback function */
3947 pmboxq->context1 = dd_data;
3948 dd_data->type = TYPE_MBOX;
3949 dd_data->context_un.mbox.pmboxq = pmboxq;
3950 dd_data->context_un.mbox.mb = (MAILBOX_t *)pbuf;
3951 dd_data->context_un.mbox.set_job = job;
3952 job->dd_data = dd_data;
3953
3954 /* state change */
3955 phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_PORT;
3956
3957 rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT);
3958 if ((rc == MBX_SUCCESS) || (rc == MBX_BUSY)) {
3959 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3960 "2969 Issued SLI_CONFIG ext-buffer "
3961 "maibox command, rc:x%x\n", rc);
3962 return 1;
3963 }
3964 lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
3965 "2970 Failed to issue SLI_CONFIG ext-buffer "
3966 "maibox command, rc:x%x\n", rc);
3967 rc = -EPIPE;
3968 goto job_error;
3969 }
3970
3971 /* wait for additoinal external buffers */
3972 job->reply->result = 0;
3973 job->job_done(job);
3974 return SLI_CONFIG_HANDLED;
3975
3976job_error:
3977 lpfc_bsg_dma_page_free(phba, dmabuf);
3978 kfree(dd_data);
3979
3980 return rc;
3981}
3982
3983/**
3984 * lpfc_bsg_handle_sli_cfg_ebuf - handle ext buffer with sli-cfg mailbox cmd
3985 * @phba: Pointer to HBA context object.
3986 * @mb: Pointer to a BSG mailbox object.
3987 * @dmabuff: Pointer to a DMA buffer descriptor.
3988 *
3989 * This routine handles the external buffer with SLI_CONFIG (0x9B) mailbox
3990 * command with multiple non-embedded external buffers.
3991 **/
3992static int
3993lpfc_bsg_handle_sli_cfg_ebuf(struct lpfc_hba *phba, struct fc_bsg_job *job,
3994 struct lpfc_dmabuf *dmabuf)
3995{
3996 int rc;
3997
3998 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3999 "2971 SLI_CONFIG buffer (type:x%x)\n",
4000 phba->mbox_ext_buf_ctx.mboxType);
4001
4002 if (phba->mbox_ext_buf_ctx.mboxType == mbox_rd) {
4003 if (phba->mbox_ext_buf_ctx.state != LPFC_BSG_MBOX_DONE) {
4004 lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
4005 "2972 SLI_CONFIG rd buffer state "
4006 "mismatch:x%x\n",
4007 phba->mbox_ext_buf_ctx.state);
4008 lpfc_bsg_mbox_ext_abort(phba);
4009 return -EPIPE;
4010 }
4011 rc = lpfc_bsg_read_ebuf_get(phba, job);
4012 if (rc == SLI_CONFIG_HANDLED)
4013 lpfc_bsg_dma_page_free(phba, dmabuf);
4014 } else { /* phba->mbox_ext_buf_ctx.mboxType == mbox_wr */
4015 if (phba->mbox_ext_buf_ctx.state != LPFC_BSG_MBOX_HOST) {
4016 lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
4017 "2973 SLI_CONFIG wr buffer state "
4018 "mismatch:x%x\n",
4019 phba->mbox_ext_buf_ctx.state);
4020 lpfc_bsg_mbox_ext_abort(phba);
4021 return -EPIPE;
4022 }
4023 rc = lpfc_bsg_write_ebuf_set(phba, job, dmabuf);
4024 }
4025 return rc;
4026}
4027
4028/**
4029 * lpfc_bsg_handle_sli_cfg_ext - handle sli-cfg mailbox with external buffer
4030 * @phba: Pointer to HBA context object.
4031 * @mb: Pointer to a BSG mailbox object.
4032 * @dmabuff: Pointer to a DMA buffer descriptor.
4033 *
4034 * This routine checkes and handles non-embedded multi-buffer SLI_CONFIG
4035 * (0x9B) mailbox commands and external buffers.
4036 **/
4037static int
4038lpfc_bsg_handle_sli_cfg_ext(struct lpfc_hba *phba, struct fc_bsg_job *job,
4039 struct lpfc_dmabuf *dmabuf)
4040{
4041 struct dfc_mbox_req *mbox_req;
4042 int rc;
4043
4044 mbox_req =
4045 (struct dfc_mbox_req *)job->request->rqst_data.h_vendor.vendor_cmd;
4046
4047 /* mbox command with/without single external buffer */
4048 if (mbox_req->extMboxTag == 0 && mbox_req->extSeqNum == 0)
4049 return SLI_CONFIG_NOT_HANDLED;
4050
4051 /* mbox command and first external buffer */
4052 if (phba->mbox_ext_buf_ctx.state == LPFC_BSG_MBOX_IDLE) {
4053 if (mbox_req->extSeqNum == 1) {
4054 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
4055 "2974 SLI_CONFIG mailbox: tag:%d, "
4056 "seq:%d\n", mbox_req->extMboxTag,
4057 mbox_req->extSeqNum);
4058 rc = lpfc_bsg_handle_sli_cfg_mbox(phba, job, dmabuf);
4059 return rc;
4060 } else
4061 goto sli_cfg_ext_error;
4062 }
4063
4064 /*
4065 * handle additional external buffers
4066 */
4067
4068 /* check broken pipe conditions */
4069 if (mbox_req->extMboxTag != phba->mbox_ext_buf_ctx.mbxTag)
4070 goto sli_cfg_ext_error;
4071 if (mbox_req->extSeqNum > phba->mbox_ext_buf_ctx.numBuf)
4072 goto sli_cfg_ext_error;
4073 if (mbox_req->extSeqNum != phba->mbox_ext_buf_ctx.seqNum + 1)
4074 goto sli_cfg_ext_error;
4075
4076 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
4077 "2975 SLI_CONFIG mailbox external buffer: "
4078 "extSta:x%x, tag:%d, seq:%d\n",
4079 phba->mbox_ext_buf_ctx.state, mbox_req->extMboxTag,
4080 mbox_req->extSeqNum);
4081 rc = lpfc_bsg_handle_sli_cfg_ebuf(phba, job, dmabuf);
4082 return rc;
4083
4084sli_cfg_ext_error:
4085 /* all other cases, broken pipe */
4086 lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
4087 "2976 SLI_CONFIG mailbox broken pipe: "
4088 "ctxSta:x%x, ctxNumBuf:%d "
4089 "ctxTag:%d, ctxSeq:%d, tag:%d, seq:%d\n",
4090 phba->mbox_ext_buf_ctx.state,
4091 phba->mbox_ext_buf_ctx.numBuf,
4092 phba->mbox_ext_buf_ctx.mbxTag,
4093 phba->mbox_ext_buf_ctx.seqNum,
4094 mbox_req->extMboxTag, mbox_req->extSeqNum);
4095
4096 lpfc_bsg_mbox_ext_session_reset(phba);
4097
4098 return -EPIPE;
4099}
4100
4101/**
2628 * lpfc_bsg_issue_mbox - issues a mailbox command on behalf of an app 4102 * lpfc_bsg_issue_mbox - issues a mailbox command on behalf of an app
2629 * @phba: Pointer to HBA context object. 4103 * @phba: Pointer to HBA context object.
2630 * @mb: Pointer to a mailbox object. 4104 * @mb: Pointer to a mailbox object.
@@ -2644,22 +4118,21 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
2644 LPFC_MBOXQ_t *pmboxq = NULL; /* internal mailbox queue */ 4118 LPFC_MBOXQ_t *pmboxq = NULL; /* internal mailbox queue */
2645 MAILBOX_t *pmb; /* shortcut to the pmboxq mailbox */ 4119 MAILBOX_t *pmb; /* shortcut to the pmboxq mailbox */
2646 /* a 4k buffer to hold the mb and extended data from/to the bsg */ 4120 /* a 4k buffer to hold the mb and extended data from/to the bsg */
2647 MAILBOX_t *mb = NULL; 4121 uint8_t *pmbx = NULL;
2648 struct bsg_job_data *dd_data = NULL; /* bsg data tracking structure */ 4122 struct bsg_job_data *dd_data = NULL; /* bsg data tracking structure */
2649 uint32_t size; 4123 struct lpfc_dmabuf *dmabuf = NULL;
2650 struct lpfc_dmabuf *rxbmp = NULL; /* for biu diag */ 4124 struct dfc_mbox_req *mbox_req;
2651 struct lpfc_dmabufext *dmp = NULL; /* for biu diag */
2652 struct ulp_bde64 *rxbpl = NULL;
2653 struct dfc_mbox_req *mbox_req = (struct dfc_mbox_req *)
2654 job->request->rqst_data.h_vendor.vendor_cmd;
2655 struct READ_EVENT_LOG_VAR *rdEventLog; 4125 struct READ_EVENT_LOG_VAR *rdEventLog;
2656 uint32_t transmit_length, receive_length, mode; 4126 uint32_t transmit_length, receive_length, mode;
4127 struct lpfc_mbx_sli4_config *sli4_config;
2657 struct lpfc_mbx_nembed_cmd *nembed_sge; 4128 struct lpfc_mbx_nembed_cmd *nembed_sge;
2658 struct mbox_header *header; 4129 struct mbox_header *header;
2659 struct ulp_bde64 *bde; 4130 struct ulp_bde64 *bde;
2660 uint8_t *ext = NULL; 4131 uint8_t *ext = NULL;
2661 int rc = 0; 4132 int rc = 0;
2662 uint8_t *from; 4133 uint8_t *from;
4134 uint32_t size;
4135
2663 4136
2664 /* in case no data is transferred */ 4137 /* in case no data is transferred */
2665 job->reply->reply_payload_rcv_len = 0; 4138 job->reply->reply_payload_rcv_len = 0;
@@ -2671,6 +4144,18 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
2671 goto job_done; 4144 goto job_done;
2672 } 4145 }
2673 4146
4147 /*
4148 * Don't allow mailbox commands to be sent when blocked or when in
4149 * the middle of discovery
4150 */
4151 if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) {
4152 rc = -EAGAIN;
4153 goto job_done;
4154 }
4155
4156 mbox_req =
4157 (struct dfc_mbox_req *)job->request->rqst_data.h_vendor.vendor_cmd;
4158
2674 /* check if requested extended data lengths are valid */ 4159 /* check if requested extended data lengths are valid */
2675 if ((mbox_req->inExtWLen > BSG_MBOX_SIZE/sizeof(uint32_t)) || 4160 if ((mbox_req->inExtWLen > BSG_MBOX_SIZE/sizeof(uint32_t)) ||
2676 (mbox_req->outExtWLen > BSG_MBOX_SIZE/sizeof(uint32_t))) { 4161 (mbox_req->outExtWLen > BSG_MBOX_SIZE/sizeof(uint32_t))) {
@@ -2678,6 +4163,32 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
2678 goto job_done; 4163 goto job_done;
2679 } 4164 }
2680 4165
4166 dmabuf = lpfc_bsg_dma_page_alloc(phba);
4167 if (!dmabuf || !dmabuf->virt) {
4168 rc = -ENOMEM;
4169 goto job_done;
4170 }
4171
4172 /* Get the mailbox command or external buffer from BSG */
4173 pmbx = (uint8_t *)dmabuf->virt;
4174 size = job->request_payload.payload_len;
4175 sg_copy_to_buffer(job->request_payload.sg_list,
4176 job->request_payload.sg_cnt, pmbx, size);
4177
4178 /* Handle possible SLI_CONFIG with non-embedded payloads */
4179 if (phba->sli_rev == LPFC_SLI_REV4) {
4180 rc = lpfc_bsg_handle_sli_cfg_ext(phba, job, dmabuf);
4181 if (rc == SLI_CONFIG_HANDLED)
4182 goto job_cont;
4183 if (rc)
4184 goto job_done;
4185 /* SLI_CONFIG_NOT_HANDLED for other mailbox commands */
4186 }
4187
4188 rc = lpfc_bsg_check_cmd_access(phba, (MAILBOX_t *)pmbx, vport);
4189 if (rc != 0)
4190 goto job_done; /* must be negative */
4191
2681 /* allocate our bsg tracking structure */ 4192 /* allocate our bsg tracking structure */
2682 dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL); 4193 dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);
2683 if (!dd_data) { 4194 if (!dd_data) {
@@ -2687,12 +4198,6 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
2687 goto job_done; 4198 goto job_done;
2688 } 4199 }
2689 4200
2690 mb = kzalloc(BSG_MBOX_SIZE, GFP_KERNEL);
2691 if (!mb) {
2692 rc = -ENOMEM;
2693 goto job_done;
2694 }
2695
2696 pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); 4201 pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
2697 if (!pmboxq) { 4202 if (!pmboxq) {
2698 rc = -ENOMEM; 4203 rc = -ENOMEM;
@@ -2700,17 +4205,8 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
2700 } 4205 }
2701 memset(pmboxq, 0, sizeof(LPFC_MBOXQ_t)); 4206 memset(pmboxq, 0, sizeof(LPFC_MBOXQ_t));
2702 4207
2703 size = job->request_payload.payload_len;
2704 sg_copy_to_buffer(job->request_payload.sg_list,
2705 job->request_payload.sg_cnt,
2706 mb, size);
2707
2708 rc = lpfc_bsg_check_cmd_access(phba, mb, vport);
2709 if (rc != 0)
2710 goto job_done; /* must be negative */
2711
2712 pmb = &pmboxq->u.mb; 4208 pmb = &pmboxq->u.mb;
2713 memcpy(pmb, mb, sizeof(*pmb)); 4209 memcpy(pmb, pmbx, sizeof(*pmb));
2714 pmb->mbxOwner = OWN_HOST; 4210 pmb->mbxOwner = OWN_HOST;
2715 pmboxq->vport = vport; 4211 pmboxq->vport = vport;
2716 4212
@@ -2727,30 +4223,13 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
2727 "0x%x while in stopped state.\n", 4223 "0x%x while in stopped state.\n",
2728 pmb->mbxCommand); 4224 pmb->mbxCommand);
2729 4225
2730 /* Don't allow mailbox commands to be sent when blocked
2731 * or when in the middle of discovery
2732 */
2733 if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) {
2734 rc = -EAGAIN;
2735 goto job_done;
2736 }
2737
2738 /* extended mailbox commands will need an extended buffer */ 4226 /* extended mailbox commands will need an extended buffer */
2739 if (mbox_req->inExtWLen || mbox_req->outExtWLen) { 4227 if (mbox_req->inExtWLen || mbox_req->outExtWLen) {
2740 ext = kzalloc(MAILBOX_EXT_SIZE, GFP_KERNEL);
2741 if (!ext) {
2742 rc = -ENOMEM;
2743 goto job_done;
2744 }
2745
2746 /* any data for the device? */ 4228 /* any data for the device? */
2747 if (mbox_req->inExtWLen) { 4229 if (mbox_req->inExtWLen) {
2748 from = (uint8_t *)mb; 4230 from = pmbx;
2749 from += sizeof(MAILBOX_t); 4231 ext = from + sizeof(MAILBOX_t);
2750 memcpy((uint8_t *)ext, from,
2751 mbox_req->inExtWLen * sizeof(uint32_t));
2752 } 4232 }
2753
2754 pmboxq->context2 = ext; 4233 pmboxq->context2 = ext;
2755 pmboxq->in_ext_byte_len = 4234 pmboxq->in_ext_byte_len =
2756 mbox_req->inExtWLen * sizeof(uint32_t); 4235 mbox_req->inExtWLen * sizeof(uint32_t);
@@ -2774,46 +4253,17 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
2774 rc = -ERANGE; 4253 rc = -ERANGE;
2775 goto job_done; 4254 goto job_done;
2776 } 4255 }
2777
2778 rxbmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
2779 if (!rxbmp) {
2780 rc = -ENOMEM;
2781 goto job_done;
2782 }
2783
2784 rxbmp->virt = lpfc_mbuf_alloc(phba, 0, &rxbmp->phys);
2785 if (!rxbmp->virt) {
2786 rc = -ENOMEM;
2787 goto job_done;
2788 }
2789
2790 INIT_LIST_HEAD(&rxbmp->list);
2791 rxbpl = (struct ulp_bde64 *) rxbmp->virt;
2792 dmp = diag_cmd_data_alloc(phba, rxbpl, transmit_length, 0);
2793 if (!dmp) {
2794 rc = -ENOMEM;
2795 goto job_done;
2796 }
2797
2798 INIT_LIST_HEAD(&dmp->dma.list);
2799 pmb->un.varBIUdiag.un.s2.xmit_bde64.addrHigh = 4256 pmb->un.varBIUdiag.un.s2.xmit_bde64.addrHigh =
2800 putPaddrHigh(dmp->dma.phys); 4257 putPaddrHigh(dmabuf->phys + sizeof(MAILBOX_t));
2801 pmb->un.varBIUdiag.un.s2.xmit_bde64.addrLow = 4258 pmb->un.varBIUdiag.un.s2.xmit_bde64.addrLow =
2802 putPaddrLow(dmp->dma.phys); 4259 putPaddrLow(dmabuf->phys + sizeof(MAILBOX_t));
2803 4260
2804 pmb->un.varBIUdiag.un.s2.rcv_bde64.addrHigh = 4261 pmb->un.varBIUdiag.un.s2.rcv_bde64.addrHigh =
2805 putPaddrHigh(dmp->dma.phys + 4262 putPaddrHigh(dmabuf->phys + sizeof(MAILBOX_t)
2806 pmb->un.varBIUdiag.un.s2. 4263 + pmb->un.varBIUdiag.un.s2.xmit_bde64.tus.f.bdeSize);
2807 xmit_bde64.tus.f.bdeSize);
2808 pmb->un.varBIUdiag.un.s2.rcv_bde64.addrLow = 4264 pmb->un.varBIUdiag.un.s2.rcv_bde64.addrLow =
2809 putPaddrLow(dmp->dma.phys + 4265 putPaddrLow(dmabuf->phys + sizeof(MAILBOX_t)
2810 pmb->un.varBIUdiag.un.s2. 4266 + pmb->un.varBIUdiag.un.s2.xmit_bde64.tus.f.bdeSize);
2811 xmit_bde64.tus.f.bdeSize);
2812
2813 /* copy the transmit data found in the mailbox extension area */
2814 from = (uint8_t *)mb;
2815 from += sizeof(MAILBOX_t);
2816 memcpy((uint8_t *)dmp->dma.virt, from, transmit_length);
2817 } else if (pmb->mbxCommand == MBX_READ_EVENT_LOG) { 4267 } else if (pmb->mbxCommand == MBX_READ_EVENT_LOG) {
2818 rdEventLog = &pmb->un.varRdEventLog; 4268 rdEventLog = &pmb->un.varRdEventLog;
2819 receive_length = rdEventLog->rcv_bde64.tus.f.bdeSize; 4269 receive_length = rdEventLog->rcv_bde64.tus.f.bdeSize;
@@ -2829,33 +4279,10 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
2829 4279
2830 /* mode zero uses a bde like biu diags command */ 4280 /* mode zero uses a bde like biu diags command */
2831 if (mode == 0) { 4281 if (mode == 0) {
2832 4282 pmb->un.varWords[3] = putPaddrLow(dmabuf->phys
2833 /* rebuild the command for sli4 using our own buffers 4283 + sizeof(MAILBOX_t));
2834 * like we do for biu diags 4284 pmb->un.varWords[4] = putPaddrHigh(dmabuf->phys
2835 */ 4285 + sizeof(MAILBOX_t));
2836
2837 rxbmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
2838 if (!rxbmp) {
2839 rc = -ENOMEM;
2840 goto job_done;
2841 }
2842
2843 rxbmp->virt = lpfc_mbuf_alloc(phba, 0, &rxbmp->phys);
2844 rxbpl = (struct ulp_bde64 *) rxbmp->virt;
2845 if (rxbpl) {
2846 INIT_LIST_HEAD(&rxbmp->list);
2847 dmp = diag_cmd_data_alloc(phba, rxbpl,
2848 receive_length, 0);
2849 }
2850
2851 if (!dmp) {
2852 rc = -ENOMEM;
2853 goto job_done;
2854 }
2855
2856 INIT_LIST_HEAD(&dmp->dma.list);
2857 pmb->un.varWords[3] = putPaddrLow(dmp->dma.phys);
2858 pmb->un.varWords[4] = putPaddrHigh(dmp->dma.phys);
2859 } 4286 }
2860 } else if (phba->sli_rev == LPFC_SLI_REV4) { 4287 } else if (phba->sli_rev == LPFC_SLI_REV4) {
2861 if (pmb->mbxCommand == MBX_DUMP_MEMORY) { 4288 if (pmb->mbxCommand == MBX_DUMP_MEMORY) {
@@ -2866,36 +4293,14 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
2866 /* receive length cannot be greater than mailbox 4293 /* receive length cannot be greater than mailbox
2867 * extension size 4294 * extension size
2868 */ 4295 */
2869 if ((receive_length == 0) || 4296 if (receive_length == 0) {
2870 (receive_length > MAILBOX_EXT_SIZE)) {
2871 rc = -ERANGE; 4297 rc = -ERANGE;
2872 goto job_done; 4298 goto job_done;
2873 } 4299 }
2874 4300 pmb->un.varWords[3] = putPaddrLow(dmabuf->phys
2875 rxbmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); 4301 + sizeof(MAILBOX_t));
2876 if (!rxbmp) { 4302 pmb->un.varWords[4] = putPaddrHigh(dmabuf->phys
2877 rc = -ENOMEM; 4303 + sizeof(MAILBOX_t));
2878 goto job_done;
2879 }
2880
2881 rxbmp->virt = lpfc_mbuf_alloc(phba, 0, &rxbmp->phys);
2882 if (!rxbmp->virt) {
2883 rc = -ENOMEM;
2884 goto job_done;
2885 }
2886
2887 INIT_LIST_HEAD(&rxbmp->list);
2888 rxbpl = (struct ulp_bde64 *) rxbmp->virt;
2889 dmp = diag_cmd_data_alloc(phba, rxbpl, receive_length,
2890 0);
2891 if (!dmp) {
2892 rc = -ENOMEM;
2893 goto job_done;
2894 }
2895
2896 INIT_LIST_HEAD(&dmp->dma.list);
2897 pmb->un.varWords[3] = putPaddrLow(dmp->dma.phys);
2898 pmb->un.varWords[4] = putPaddrHigh(dmp->dma.phys);
2899 } else if ((pmb->mbxCommand == MBX_UPDATE_CFG) && 4304 } else if ((pmb->mbxCommand == MBX_UPDATE_CFG) &&
2900 pmb->un.varUpdateCfg.co) { 4305 pmb->un.varUpdateCfg.co) {
2901 bde = (struct ulp_bde64 *)&pmb->un.varWords[4]; 4306 bde = (struct ulp_bde64 *)&pmb->un.varWords[4];
@@ -2905,102 +4310,53 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
2905 rc = -ERANGE; 4310 rc = -ERANGE;
2906 goto job_done; 4311 goto job_done;
2907 } 4312 }
2908 4313 bde->addrHigh = putPaddrHigh(dmabuf->phys
2909 rxbmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); 4314 + sizeof(MAILBOX_t));
2910 if (!rxbmp) { 4315 bde->addrLow = putPaddrLow(dmabuf->phys
2911 rc = -ENOMEM; 4316 + sizeof(MAILBOX_t));
2912 goto job_done;
2913 }
2914
2915 rxbmp->virt = lpfc_mbuf_alloc(phba, 0, &rxbmp->phys);
2916 if (!rxbmp->virt) {
2917 rc = -ENOMEM;
2918 goto job_done;
2919 }
2920
2921 INIT_LIST_HEAD(&rxbmp->list);
2922 rxbpl = (struct ulp_bde64 *) rxbmp->virt;
2923 dmp = diag_cmd_data_alloc(phba, rxbpl,
2924 bde->tus.f.bdeSize, 0);
2925 if (!dmp) {
2926 rc = -ENOMEM;
2927 goto job_done;
2928 }
2929
2930 INIT_LIST_HEAD(&dmp->dma.list);
2931 bde->addrHigh = putPaddrHigh(dmp->dma.phys);
2932 bde->addrLow = putPaddrLow(dmp->dma.phys);
2933
2934 /* copy the transmit data found in the mailbox
2935 * extension area
2936 */
2937 from = (uint8_t *)mb;
2938 from += sizeof(MAILBOX_t);
2939 memcpy((uint8_t *)dmp->dma.virt, from,
2940 bde->tus.f.bdeSize);
2941 } else if (pmb->mbxCommand == MBX_SLI4_CONFIG) { 4317 } else if (pmb->mbxCommand == MBX_SLI4_CONFIG) {
2942 /* rebuild the command for sli4 using our own buffers 4318 /* Handling non-embedded SLI_CONFIG mailbox command */
2943 * like we do for biu diags 4319 sli4_config = &pmboxq->u.mqe.un.sli4_config;
2944 */ 4320 if (!bf_get(lpfc_mbox_hdr_emb,
2945 header = (struct mbox_header *)&pmb->un.varWords[0]; 4321 &sli4_config->header.cfg_mhdr)) {
2946 nembed_sge = (struct lpfc_mbx_nembed_cmd *) 4322 /* rebuild the command for sli4 using our
2947 &pmb->un.varWords[0]; 4323 * own buffers like we do for biu diags
2948 receive_length = nembed_sge->sge[0].length; 4324 */
2949 4325 header = (struct mbox_header *)
2950 /* receive length cannot be greater than mailbox 4326 &pmb->un.varWords[0];
2951 * extension size 4327 nembed_sge = (struct lpfc_mbx_nembed_cmd *)
2952 */ 4328 &pmb->un.varWords[0];
2953 if ((receive_length == 0) || 4329 receive_length = nembed_sge->sge[0].length;
2954 (receive_length > MAILBOX_EXT_SIZE)) { 4330
2955 rc = -ERANGE; 4331 /* receive length cannot be greater than
2956 goto job_done; 4332 * mailbox extension size
2957 } 4333 */
2958 4334 if ((receive_length == 0) ||
2959 rxbmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); 4335 (receive_length > MAILBOX_EXT_SIZE)) {
2960 if (!rxbmp) { 4336 rc = -ERANGE;
2961 rc = -ENOMEM; 4337 goto job_done;
2962 goto job_done; 4338 }
2963 }
2964
2965 rxbmp->virt = lpfc_mbuf_alloc(phba, 0, &rxbmp->phys);
2966 if (!rxbmp->virt) {
2967 rc = -ENOMEM;
2968 goto job_done;
2969 }
2970 4339
2971 INIT_LIST_HEAD(&rxbmp->list); 4340 nembed_sge->sge[0].pa_hi =
2972 rxbpl = (struct ulp_bde64 *) rxbmp->virt; 4341 putPaddrHigh(dmabuf->phys
2973 dmp = diag_cmd_data_alloc(phba, rxbpl, receive_length, 4342 + sizeof(MAILBOX_t));
2974 0); 4343 nembed_sge->sge[0].pa_lo =
2975 if (!dmp) { 4344 putPaddrLow(dmabuf->phys
2976 rc = -ENOMEM; 4345 + sizeof(MAILBOX_t));
2977 goto job_done;
2978 } 4346 }
2979
2980 INIT_LIST_HEAD(&dmp->dma.list);
2981 nembed_sge->sge[0].pa_hi = putPaddrHigh(dmp->dma.phys);
2982 nembed_sge->sge[0].pa_lo = putPaddrLow(dmp->dma.phys);
2983 /* copy the transmit data found in the mailbox
2984 * extension area
2985 */
2986 from = (uint8_t *)mb;
2987 from += sizeof(MAILBOX_t);
2988 memcpy((uint8_t *)dmp->dma.virt, from,
2989 header->cfg_mhdr.payload_length);
2990 } 4347 }
2991 } 4348 }
2992 4349
2993 dd_data->context_un.mbox.rxbmp = rxbmp; 4350 dd_data->context_un.mbox.dmabuffers = dmabuf;
2994 dd_data->context_un.mbox.dmp = dmp;
2995 4351
2996 /* setup wake call as IOCB callback */ 4352 /* setup wake call as IOCB callback */
2997 pmboxq->mbox_cmpl = lpfc_bsg_wake_mbox_wait; 4353 pmboxq->mbox_cmpl = lpfc_bsg_issue_mbox_cmpl;
2998 4354
2999 /* setup context field to pass wait_queue pointer to wake function */ 4355 /* setup context field to pass wait_queue pointer to wake function */
3000 pmboxq->context1 = dd_data; 4356 pmboxq->context1 = dd_data;
3001 dd_data->type = TYPE_MBOX; 4357 dd_data->type = TYPE_MBOX;
3002 dd_data->context_un.mbox.pmboxq = pmboxq; 4358 dd_data->context_un.mbox.pmboxq = pmboxq;
3003 dd_data->context_un.mbox.mb = mb; 4359 dd_data->context_un.mbox.mb = (MAILBOX_t *)pmbx;
3004 dd_data->context_un.mbox.set_job = job; 4360 dd_data->context_un.mbox.set_job = job;
3005 dd_data->context_un.mbox.ext = ext; 4361 dd_data->context_un.mbox.ext = ext;
3006 dd_data->context_un.mbox.mbOffset = mbox_req->mbOffset; 4362 dd_data->context_un.mbox.mbOffset = mbox_req->mbOffset;
@@ -3017,11 +4373,11 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
3017 } 4373 }
3018 4374
3019 /* job finished, copy the data */ 4375 /* job finished, copy the data */
3020 memcpy(mb, pmb, sizeof(*pmb)); 4376 memcpy(pmbx, pmb, sizeof(*pmb));
3021 job->reply->reply_payload_rcv_len = 4377 job->reply->reply_payload_rcv_len =
3022 sg_copy_from_buffer(job->reply_payload.sg_list, 4378 sg_copy_from_buffer(job->reply_payload.sg_list,
3023 job->reply_payload.sg_cnt, 4379 job->reply_payload.sg_cnt,
3024 mb, size); 4380 pmbx, size);
3025 /* not waiting mbox already done */ 4381 /* not waiting mbox already done */
3026 rc = 0; 4382 rc = 0;
3027 goto job_done; 4383 goto job_done;
@@ -3033,22 +4389,12 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
3033 4389
3034job_done: 4390job_done:
3035 /* common exit for error or job completed inline */ 4391 /* common exit for error or job completed inline */
3036 kfree(mb);
3037 if (pmboxq) 4392 if (pmboxq)
3038 mempool_free(pmboxq, phba->mbox_mem_pool); 4393 mempool_free(pmboxq, phba->mbox_mem_pool);
3039 kfree(ext); 4394 lpfc_bsg_dma_page_free(phba, dmabuf);
3040 if (dmp) {
3041 dma_free_coherent(&phba->pcidev->dev,
3042 dmp->size, dmp->dma.virt,
3043 dmp->dma.phys);
3044 kfree(dmp);
3045 }
3046 if (rxbmp) {
3047 lpfc_mbuf_free(phba, rxbmp->virt, rxbmp->phys);
3048 kfree(rxbmp);
3049 }
3050 kfree(dd_data); 4395 kfree(dd_data);
3051 4396
4397job_cont:
3052 return rc; 4398 return rc;
3053} 4399}
3054 4400
@@ -3061,37 +4407,28 @@ lpfc_bsg_mbox_cmd(struct fc_bsg_job *job)
3061{ 4407{
3062 struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata; 4408 struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata;
3063 struct lpfc_hba *phba = vport->phba; 4409 struct lpfc_hba *phba = vport->phba;
4410 struct dfc_mbox_req *mbox_req;
3064 int rc = 0; 4411 int rc = 0;
3065 4412
3066 /* in case no data is transferred */ 4413 /* mix-and-match backward compatibility */
3067 job->reply->reply_payload_rcv_len = 0; 4414 job->reply->reply_payload_rcv_len = 0;
3068 if (job->request_len < 4415 if (job->request_len <
3069 sizeof(struct fc_bsg_request) + sizeof(struct dfc_mbox_req)) { 4416 sizeof(struct fc_bsg_request) + sizeof(struct dfc_mbox_req)) {
3070 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC, 4417 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3071 "2737 Received MBOX_REQ request below " 4418 "2737 Mix-and-match backward compability "
3072 "minimum size\n"); 4419 "between MBOX_REQ old size:%d and "
3073 rc = -EINVAL; 4420 "new request size:%d\n",
3074 goto job_error; 4421 (int)(job->request_len -
3075 } 4422 sizeof(struct fc_bsg_request)),
3076 4423 (int)sizeof(struct dfc_mbox_req));
3077 if (job->request_payload.payload_len != BSG_MBOX_SIZE) { 4424 mbox_req = (struct dfc_mbox_req *)
3078 rc = -EINVAL; 4425 job->request->rqst_data.h_vendor.vendor_cmd;
3079 goto job_error; 4426 mbox_req->extMboxTag = 0;
3080 } 4427 mbox_req->extSeqNum = 0;
3081
3082 if (job->reply_payload.payload_len != BSG_MBOX_SIZE) {
3083 rc = -EINVAL;
3084 goto job_error;
3085 }
3086
3087 if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) {
3088 rc = -EAGAIN;
3089 goto job_error;
3090 } 4428 }
3091 4429
3092 rc = lpfc_bsg_issue_mbox(phba, job, vport); 4430 rc = lpfc_bsg_issue_mbox(phba, job, vport);
3093 4431
3094job_error:
3095 if (rc == 0) { 4432 if (rc == 0) {
3096 /* job done */ 4433 /* job done */
3097 job->reply->result = 0; 4434 job->reply->result = 0;
@@ -3422,10 +4759,16 @@ lpfc_bsg_hst_vendor(struct fc_bsg_job *job)
3422 rc = lpfc_bsg_send_mgmt_rsp(job); 4759 rc = lpfc_bsg_send_mgmt_rsp(job);
3423 break; 4760 break;
3424 case LPFC_BSG_VENDOR_DIAG_MODE: 4761 case LPFC_BSG_VENDOR_DIAG_MODE:
3425 rc = lpfc_bsg_diag_mode(job); 4762 rc = lpfc_bsg_diag_loopback_mode(job);
4763 break;
4764 case LPFC_BSG_VENDOR_DIAG_MODE_END:
4765 rc = lpfc_sli4_bsg_diag_mode_end(job);
4766 break;
4767 case LPFC_BSG_VENDOR_DIAG_RUN_LOOPBACK:
4768 rc = lpfc_bsg_diag_loopback_run(job);
3426 break; 4769 break;
3427 case LPFC_BSG_VENDOR_DIAG_TEST: 4770 case LPFC_BSG_VENDOR_LINK_DIAG_TEST:
3428 rc = lpfc_bsg_diag_test(job); 4771 rc = lpfc_sli4_bsg_link_diag_test(job);
3429 break; 4772 break;
3430 case LPFC_BSG_VENDOR_GET_MGMT_REV: 4773 case LPFC_BSG_VENDOR_GET_MGMT_REV:
3431 rc = lpfc_bsg_get_dfc_rev(job); 4774 rc = lpfc_bsg_get_dfc_rev(job);
@@ -3544,6 +4887,8 @@ lpfc_bsg_timeout(struct fc_bsg_job *job)
3544 /* the mbox completion handler can now be run */ 4887 /* the mbox completion handler can now be run */
3545 spin_unlock_irqrestore(&phba->ct_ev_lock, flags); 4888 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
3546 job->job_done(job); 4889 job->job_done(job);
4890 if (phba->mbox_ext_buf_ctx.state == LPFC_BSG_MBOX_PORT)
4891 phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_ABTS;
3547 break; 4892 break;
3548 case TYPE_MENLO: 4893 case TYPE_MENLO:
3549 menlo = &dd_data->context_un.menlo; 4894 menlo = &dd_data->context_un.menlo;
diff --git a/drivers/scsi/lpfc/lpfc_bsg.h b/drivers/scsi/lpfc/lpfc_bsg.h
index b542aca6f5ae..c8c2b47ea886 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.h
+++ b/drivers/scsi/lpfc/lpfc_bsg.h
@@ -24,15 +24,17 @@
24 * These are the vendor unique structures passed in using the bsg 24 * These are the vendor unique structures passed in using the bsg
25 * FC_BSG_HST_VENDOR message code type. 25 * FC_BSG_HST_VENDOR message code type.
26 */ 26 */
27#define LPFC_BSG_VENDOR_SET_CT_EVENT 1 27#define LPFC_BSG_VENDOR_SET_CT_EVENT 1
28#define LPFC_BSG_VENDOR_GET_CT_EVENT 2 28#define LPFC_BSG_VENDOR_GET_CT_EVENT 2
29#define LPFC_BSG_VENDOR_SEND_MGMT_RESP 3 29#define LPFC_BSG_VENDOR_SEND_MGMT_RESP 3
30#define LPFC_BSG_VENDOR_DIAG_MODE 4 30#define LPFC_BSG_VENDOR_DIAG_MODE 4
31#define LPFC_BSG_VENDOR_DIAG_TEST 5 31#define LPFC_BSG_VENDOR_DIAG_RUN_LOOPBACK 5
32#define LPFC_BSG_VENDOR_GET_MGMT_REV 6 32#define LPFC_BSG_VENDOR_GET_MGMT_REV 6
33#define LPFC_BSG_VENDOR_MBOX 7 33#define LPFC_BSG_VENDOR_MBOX 7
34#define LPFC_BSG_VENDOR_MENLO_CMD 8 34#define LPFC_BSG_VENDOR_MENLO_CMD 8
35#define LPFC_BSG_VENDOR_MENLO_DATA 9 35#define LPFC_BSG_VENDOR_MENLO_DATA 9
36#define LPFC_BSG_VENDOR_DIAG_MODE_END 10
37#define LPFC_BSG_VENDOR_LINK_DIAG_TEST 11
36 38
37struct set_ct_event { 39struct set_ct_event {
38 uint32_t command; 40 uint32_t command;
@@ -67,10 +69,25 @@ struct diag_mode_set {
67 uint32_t timeout; 69 uint32_t timeout;
68}; 70};
69 71
72struct sli4_link_diag {
73 uint32_t command;
74 uint32_t timeout;
75 uint32_t test_id;
76 uint32_t loops;
77 uint32_t test_version;
78 uint32_t error_action;
79};
80
70struct diag_mode_test { 81struct diag_mode_test {
71 uint32_t command; 82 uint32_t command;
72}; 83};
73 84
85struct diag_status {
86 uint32_t mbox_status;
87 uint32_t shdr_status;
88 uint32_t shdr_add_status;
89};
90
74#define LPFC_WWNN_TYPE 0 91#define LPFC_WWNN_TYPE 0
75#define LPFC_WWPN_TYPE 1 92#define LPFC_WWPN_TYPE 1
76 93
@@ -92,11 +109,15 @@ struct get_mgmt_rev_reply {
92}; 109};
93 110
94#define BSG_MBOX_SIZE 4096 /* mailbox command plus extended data */ 111#define BSG_MBOX_SIZE 4096 /* mailbox command plus extended data */
112
113/* BSG mailbox request header */
95struct dfc_mbox_req { 114struct dfc_mbox_req {
96 uint32_t command; 115 uint32_t command;
97 uint32_t mbOffset; 116 uint32_t mbOffset;
98 uint32_t inExtWLen; 117 uint32_t inExtWLen;
99 uint32_t outExtWLen; 118 uint32_t outExtWLen;
119 uint32_t extMboxTag;
120 uint32_t extSeqNum;
100}; 121};
101 122
102/* Used for menlo command or menlo data. The xri is only used for menlo data */ 123/* Used for menlo command or menlo data. The xri is only used for menlo data */
@@ -171,7 +192,7 @@ struct lpfc_sli_config_mse {
171#define lpfc_mbox_sli_config_mse_len_WORD buf_len 192#define lpfc_mbox_sli_config_mse_len_WORD buf_len
172}; 193};
173 194
174struct lpfc_sli_config_subcmd_hbd { 195struct lpfc_sli_config_hbd {
175 uint32_t buf_len; 196 uint32_t buf_len;
176#define lpfc_mbox_sli_config_ecmn_hbd_len_SHIFT 0 197#define lpfc_mbox_sli_config_ecmn_hbd_len_SHIFT 0
177#define lpfc_mbox_sli_config_ecmn_hbd_len_MASK 0xffffff 198#define lpfc_mbox_sli_config_ecmn_hbd_len_MASK 0xffffff
@@ -194,21 +215,39 @@ struct lpfc_sli_config_hdr {
194 uint32_t reserved5; 215 uint32_t reserved5;
195}; 216};
196 217
197struct lpfc_sli_config_generic { 218struct lpfc_sli_config_emb0_subsys {
198 struct lpfc_sli_config_hdr sli_config_hdr; 219 struct lpfc_sli_config_hdr sli_config_hdr;
199#define LPFC_MBX_SLI_CONFIG_MAX_MSE 19 220#define LPFC_MBX_SLI_CONFIG_MAX_MSE 19
200 struct lpfc_sli_config_mse mse[LPFC_MBX_SLI_CONFIG_MAX_MSE]; 221 struct lpfc_sli_config_mse mse[LPFC_MBX_SLI_CONFIG_MAX_MSE];
222 uint32_t padding;
223 uint32_t word64;
224#define lpfc_emb0_subcmnd_opcode_SHIFT 0
225#define lpfc_emb0_subcmnd_opcode_MASK 0xff
226#define lpfc_emb0_subcmnd_opcode_WORD word64
227#define lpfc_emb0_subcmnd_subsys_SHIFT 8
228#define lpfc_emb0_subcmnd_subsys_MASK 0xff
229#define lpfc_emb0_subcmnd_subsys_WORD word64
230/* Subsystem FCOE (0x0C) OpCodes */
231#define SLI_CONFIG_SUBSYS_FCOE 0x0C
232#define FCOE_OPCODE_READ_FCF 0x08
233#define FCOE_OPCODE_ADD_FCF 0x09
201}; 234};
202 235
203struct lpfc_sli_config_subcmnd { 236struct lpfc_sli_config_emb1_subsys {
204 struct lpfc_sli_config_hdr sli_config_hdr; 237 struct lpfc_sli_config_hdr sli_config_hdr;
205 uint32_t word6; 238 uint32_t word6;
206#define lpfc_subcmnd_opcode_SHIFT 0 239#define lpfc_emb1_subcmnd_opcode_SHIFT 0
207#define lpfc_subcmnd_opcode_MASK 0xff 240#define lpfc_emb1_subcmnd_opcode_MASK 0xff
208#define lpfc_subcmnd_opcode_WORD word6 241#define lpfc_emb1_subcmnd_opcode_WORD word6
209#define lpfc_subcmnd_subsys_SHIFT 8 242#define lpfc_emb1_subcmnd_subsys_SHIFT 8
210#define lpfc_subcmnd_subsys_MASK 0xff 243#define lpfc_emb1_subcmnd_subsys_MASK 0xff
211#define lpfc_subcmnd_subsys_WORD word6 244#define lpfc_emb1_subcmnd_subsys_WORD word6
245/* Subsystem COMN (0x01) OpCodes */
246#define SLI_CONFIG_SUBSYS_COMN 0x01
247#define COMN_OPCODE_READ_OBJECT 0xAB
248#define COMN_OPCODE_WRITE_OBJECT 0xAC
249#define COMN_OPCODE_READ_OBJECT_LIST 0xAD
250#define COMN_OPCODE_DELETE_OBJECT 0xAE
212 uint32_t timeout; 251 uint32_t timeout;
213 uint32_t request_length; 252 uint32_t request_length;
214 uint32_t word9; 253 uint32_t word9;
@@ -222,8 +261,8 @@ struct lpfc_sli_config_subcmnd {
222 uint32_t rd_offset; 261 uint32_t rd_offset;
223 uint32_t obj_name[26]; 262 uint32_t obj_name[26];
224 uint32_t hbd_count; 263 uint32_t hbd_count;
225#define LPFC_MBX_SLI_CONFIG_MAX_HBD 10 264#define LPFC_MBX_SLI_CONFIG_MAX_HBD 8
226 struct lpfc_sli_config_subcmd_hbd hbd[LPFC_MBX_SLI_CONFIG_MAX_HBD]; 265 struct lpfc_sli_config_hbd hbd[LPFC_MBX_SLI_CONFIG_MAX_HBD];
227}; 266};
228 267
229struct lpfc_sli_config_mbox { 268struct lpfc_sli_config_mbox {
@@ -235,7 +274,11 @@ struct lpfc_sli_config_mbox {
235#define lpfc_mqe_command_MASK 0x000000FF 274#define lpfc_mqe_command_MASK 0x000000FF
236#define lpfc_mqe_command_WORD word0 275#define lpfc_mqe_command_WORD word0
237 union { 276 union {
238 struct lpfc_sli_config_generic sli_config_generic; 277 struct lpfc_sli_config_emb0_subsys sli_config_emb0_subsys;
239 struct lpfc_sli_config_subcmnd sli_config_subcmnd; 278 struct lpfc_sli_config_emb1_subsys sli_config_emb1_subsys;
240 } un; 279 } un;
241}; 280};
281
282/* driver only */
283#define SLI_CONFIG_NOT_HANDLED 0
284#define SLI_CONFIG_HANDLED 1
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index f14db2d17f29..11e26a26b5d1 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -867,6 +867,8 @@ struct mbox_header {
867#define LPFC_MBOX_OPCODE_FCOE_DELETE_FCF 0x0A 867#define LPFC_MBOX_OPCODE_FCOE_DELETE_FCF 0x0A
868#define LPFC_MBOX_OPCODE_FCOE_POST_HDR_TEMPLATE 0x0B 868#define LPFC_MBOX_OPCODE_FCOE_POST_HDR_TEMPLATE 0x0B
869#define LPFC_MBOX_OPCODE_FCOE_REDISCOVER_FCF 0x10 869#define LPFC_MBOX_OPCODE_FCOE_REDISCOVER_FCF 0x10
870#define LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_STATE 0x22
871#define LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_LOOPBACK 0x23
870 872
871/* Mailbox command structures */ 873/* Mailbox command structures */
872struct eq_context { 874struct eq_context {
@@ -1308,6 +1310,83 @@ struct lpfc_id_range {
1308#define lpfc_mbx_rsrc_id_word4_1_WORD word5 1310#define lpfc_mbx_rsrc_id_word4_1_WORD word5
1309}; 1311};
1310 1312
1313struct lpfc_mbx_set_link_diag_state {
1314 struct mbox_header header;
1315 union {
1316 struct {
1317 uint32_t word0;
1318#define lpfc_mbx_set_diag_state_diag_SHIFT 0
1319#define lpfc_mbx_set_diag_state_diag_MASK 0x00000001
1320#define lpfc_mbx_set_diag_state_diag_WORD word0
1321#define lpfc_mbx_set_diag_state_link_num_SHIFT 16
1322#define lpfc_mbx_set_diag_state_link_num_MASK 0x0000003F
1323#define lpfc_mbx_set_diag_state_link_num_WORD word0
1324#define lpfc_mbx_set_diag_state_link_type_SHIFT 22
1325#define lpfc_mbx_set_diag_state_link_type_MASK 0x00000003
1326#define lpfc_mbx_set_diag_state_link_type_WORD word0
1327 } req;
1328 struct {
1329 uint32_t word0;
1330 } rsp;
1331 } u;
1332};
1333
1334struct lpfc_mbx_set_link_diag_loopback {
1335 struct mbox_header header;
1336 union {
1337 struct {
1338 uint32_t word0;
1339#define lpfc_mbx_set_diag_lpbk_type_SHIFT 0
1340#define lpfc_mbx_set_diag_lpbk_type_MASK 0x00000001
1341#define lpfc_mbx_set_diag_lpbk_type_WORD word0
1342#define LPFC_DIAG_LOOPBACK_TYPE_DISABLE 0x0
1343#define LPFC_DIAG_LOOPBACK_TYPE_INTERNAL 0x1
1344#define LPFC_DIAG_LOOPBACK_TYPE_EXTERNAL 0x2
1345#define lpfc_mbx_set_diag_lpbk_link_num_SHIFT 16
1346#define lpfc_mbx_set_diag_lpbk_link_num_MASK 0x0000003F
1347#define lpfc_mbx_set_diag_lpbk_link_num_WORD word0
1348#define lpfc_mbx_set_diag_lpbk_link_type_SHIFT 22
1349#define lpfc_mbx_set_diag_lpbk_link_type_MASK 0x00000003
1350#define lpfc_mbx_set_diag_lpbk_link_type_WORD word0
1351 } req;
1352 struct {
1353 uint32_t word0;
1354 } rsp;
1355 } u;
1356};
1357
1358struct lpfc_mbx_run_link_diag_test {
1359 struct mbox_header header;
1360 union {
1361 struct {
1362 uint32_t word0;
1363#define lpfc_mbx_run_diag_test_link_num_SHIFT 16
1364#define lpfc_mbx_run_diag_test_link_num_MASK 0x0000003F
1365#define lpfc_mbx_run_diag_test_link_num_WORD word0
1366#define lpfc_mbx_run_diag_test_link_type_SHIFT 22
1367#define lpfc_mbx_run_diag_test_link_type_MASK 0x00000003
1368#define lpfc_mbx_run_diag_test_link_type_WORD word0
1369 uint32_t word1;
1370#define lpfc_mbx_run_diag_test_test_id_SHIFT 0
1371#define lpfc_mbx_run_diag_test_test_id_MASK 0x0000FFFF
1372#define lpfc_mbx_run_diag_test_test_id_WORD word1
1373#define lpfc_mbx_run_diag_test_loops_SHIFT 16
1374#define lpfc_mbx_run_diag_test_loops_MASK 0x0000FFFF
1375#define lpfc_mbx_run_diag_test_loops_WORD word1
1376 uint32_t word2;
1377#define lpfc_mbx_run_diag_test_test_ver_SHIFT 0
1378#define lpfc_mbx_run_diag_test_test_ver_MASK 0x0000FFFF
1379#define lpfc_mbx_run_diag_test_test_ver_WORD word2
1380#define lpfc_mbx_run_diag_test_err_act_SHIFT 16
1381#define lpfc_mbx_run_diag_test_err_act_MASK 0x000000FF
1382#define lpfc_mbx_run_diag_test_err_act_WORD word2
1383 } req;
1384 struct {
1385 uint32_t word0;
1386 } rsp;
1387 } u;
1388};
1389
1311/* 1390/*
1312 * struct lpfc_mbx_alloc_rsrc_extents: 1391 * struct lpfc_mbx_alloc_rsrc_extents:
1313 * A mbox is generically 256 bytes long. An SLI4_CONFIG mailbox requires 1392 * A mbox is generically 256 bytes long. An SLI4_CONFIG mailbox requires
@@ -2553,6 +2632,9 @@ struct lpfc_mqe {
2553 struct lpfc_mbx_supp_pages supp_pages; 2632 struct lpfc_mbx_supp_pages supp_pages;
2554 struct lpfc_mbx_pc_sli4_params sli4_params; 2633 struct lpfc_mbx_pc_sli4_params sli4_params;
2555 struct lpfc_mbx_get_sli4_parameters get_sli4_parameters; 2634 struct lpfc_mbx_get_sli4_parameters get_sli4_parameters;
2635 struct lpfc_mbx_set_link_diag_state link_diag_state;
2636 struct lpfc_mbx_set_link_diag_loopback link_diag_loopback;
2637 struct lpfc_mbx_run_link_diag_test link_diag_test;
2556 struct lpfc_mbx_get_func_cfg get_func_cfg; 2638 struct lpfc_mbx_get_func_cfg get_func_cfg;
2557 struct lpfc_mbx_get_prof_cfg get_prof_cfg; 2639 struct lpfc_mbx_get_prof_cfg get_prof_cfg;
2558 struct lpfc_mbx_nop nop; 2640 struct lpfc_mbx_nop nop;
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 09632ea689e9..148b98ddbb1d 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -4247,6 +4247,14 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
4247 phba->fcf.redisc_wait.data = (unsigned long)phba; 4247 phba->fcf.redisc_wait.data = (unsigned long)phba;
4248 4248
4249 /* 4249 /*
4250 * Control structure for handling external multi-buffer mailbox
4251 * command pass-through.
4252 */
4253 memset((uint8_t *)&phba->mbox_ext_buf_ctx, 0,
4254 sizeof(struct lpfc_mbox_ext_buf_ctx));
4255 INIT_LIST_HEAD(&phba->mbox_ext_buf_ctx.ext_dmabuf_list);
4256
4257 /*
4250 * We need to do a READ_CONFIG mailbox command here before 4258 * We need to do a READ_CONFIG mailbox command here before
4251 * calling lpfc_get_cfgparam. For VFs this will report the 4259 * calling lpfc_get_cfgparam. For VFs this will report the
4252 * MAX_XRI, MAX_VPI, MAX_RPI, MAX_IOCB, and MAX_VFI settings. 4260 * MAX_XRI, MAX_VPI, MAX_RPI, MAX_IOCB, and MAX_VFI settings.