diff options
Diffstat (limited to 'drivers/s390/scsi/zfcp_fsf.c')
-rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 137 |
1 files changed, 127 insertions, 10 deletions
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index af75fd2ef1e2..23dd9088153f 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c | |||
@@ -961,7 +961,6 @@ static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req) | |||
961 | { | 961 | { |
962 | struct zfcp_adapter *adapter = req->adapter; | 962 | struct zfcp_adapter *adapter = req->adapter; |
963 | struct zfcp_send_ct *send_ct = req->data; | 963 | struct zfcp_send_ct *send_ct = req->data; |
964 | struct zfcp_port *port = send_ct->port; | ||
965 | struct fsf_qtcb_header *header = &req->qtcb->header; | 964 | struct fsf_qtcb_header *header = &req->qtcb->header; |
966 | 965 | ||
967 | send_ct->status = -EINVAL; | 966 | send_ct->status = -EINVAL; |
@@ -980,17 +979,14 @@ static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req) | |||
980 | case FSF_ADAPTER_STATUS_AVAILABLE: | 979 | case FSF_ADAPTER_STATUS_AVAILABLE: |
981 | switch (header->fsf_status_qual.word[0]){ | 980 | switch (header->fsf_status_qual.word[0]){ |
982 | case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: | 981 | case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: |
983 | zfcp_test_link(port); | ||
984 | case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: | 982 | case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: |
985 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 983 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
986 | break; | 984 | break; |
987 | } | 985 | } |
988 | break; | 986 | break; |
989 | case FSF_ACCESS_DENIED: | 987 | case FSF_ACCESS_DENIED: |
990 | zfcp_fsf_access_denied_port(req, port); | ||
991 | break; | 988 | break; |
992 | case FSF_PORT_BOXED: | 989 | case FSF_PORT_BOXED: |
993 | zfcp_erp_port_boxed(port, 49, req); | ||
994 | req->status |= ZFCP_STATUS_FSFREQ_ERROR | | 990 | req->status |= ZFCP_STATUS_FSFREQ_ERROR | |
995 | ZFCP_STATUS_FSFREQ_RETRY; | 991 | ZFCP_STATUS_FSFREQ_RETRY; |
996 | break; | 992 | break; |
@@ -1041,8 +1037,8 @@ static int zfcp_fsf_setup_sbals(struct zfcp_fsf_req *req, | |||
1041 | int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool, | 1037 | int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool, |
1042 | struct zfcp_erp_action *erp_action) | 1038 | struct zfcp_erp_action *erp_action) |
1043 | { | 1039 | { |
1044 | struct zfcp_port *port = ct->port; | 1040 | struct zfcp_wka_port *wka_port = ct->wka_port; |
1045 | struct zfcp_adapter *adapter = port->adapter; | 1041 | struct zfcp_adapter *adapter = wka_port->adapter; |
1046 | struct zfcp_fsf_req *req; | 1042 | struct zfcp_fsf_req *req; |
1047 | int ret = -EIO; | 1043 | int ret = -EIO; |
1048 | 1044 | ||
@@ -1063,7 +1059,7 @@ int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool, | |||
1063 | goto failed_send; | 1059 | goto failed_send; |
1064 | 1060 | ||
1065 | req->handler = zfcp_fsf_send_ct_handler; | 1061 | req->handler = zfcp_fsf_send_ct_handler; |
1066 | req->qtcb->header.port_handle = port->handle; | 1062 | req->qtcb->header.port_handle = wka_port->handle; |
1067 | req->qtcb->bottom.support.service_class = FSF_CLASS_3; | 1063 | req->qtcb->bottom.support.service_class = FSF_CLASS_3; |
1068 | req->qtcb->bottom.support.timeout = ct->timeout; | 1064 | req->qtcb->bottom.support.timeout = ct->timeout; |
1069 | req->data = ct; | 1065 | req->data = ct; |
@@ -1435,9 +1431,6 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req) | |||
1435 | * another GID_PN straight after a port has been opened. | 1431 | * another GID_PN straight after a port has been opened. |
1436 | * Alternately, an ADISC/PDISC ELS should suffice, as well. | 1432 | * Alternately, an ADISC/PDISC ELS should suffice, as well. |
1437 | */ | 1433 | */ |
1438 | if (atomic_read(&port->status) & ZFCP_STATUS_PORT_NO_WWPN) | ||
1439 | break; | ||
1440 | |||
1441 | plogi = (struct fsf_plogi *) req->qtcb->bottom.support.els; | 1434 | plogi = (struct fsf_plogi *) req->qtcb->bottom.support.els; |
1442 | if (req->qtcb->bottom.support.els1_length >= sizeof(*plogi)) { | 1435 | if (req->qtcb->bottom.support.els1_length >= sizeof(*plogi)) { |
1443 | if (plogi->serv_param.wwpn != port->wwpn) | 1436 | if (plogi->serv_param.wwpn != port->wwpn) |
@@ -1568,6 +1561,130 @@ out: | |||
1568 | return retval; | 1561 | return retval; |
1569 | } | 1562 | } |
1570 | 1563 | ||
1564 | static void zfcp_fsf_open_wka_port_handler(struct zfcp_fsf_req *req) | ||
1565 | { | ||
1566 | struct zfcp_wka_port *wka_port = req->data; | ||
1567 | struct fsf_qtcb_header *header = &req->qtcb->header; | ||
1568 | |||
1569 | if (req->status & ZFCP_STATUS_FSFREQ_ERROR) { | ||
1570 | wka_port->status = ZFCP_WKA_PORT_OFFLINE; | ||
1571 | goto out; | ||
1572 | } | ||
1573 | |||
1574 | switch (header->fsf_status) { | ||
1575 | case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED: | ||
1576 | dev_warn(&req->adapter->ccw_device->dev, | ||
1577 | "Opening WKA port 0x%x failed\n", wka_port->d_id); | ||
1578 | case FSF_ADAPTER_STATUS_AVAILABLE: | ||
1579 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | ||
1580 | case FSF_ACCESS_DENIED: | ||
1581 | wka_port->status = ZFCP_WKA_PORT_OFFLINE; | ||
1582 | break; | ||
1583 | case FSF_PORT_ALREADY_OPEN: | ||
1584 | case FSF_GOOD: | ||
1585 | wka_port->handle = header->port_handle; | ||
1586 | wka_port->status = ZFCP_WKA_PORT_ONLINE; | ||
1587 | } | ||
1588 | out: | ||
1589 | wake_up(&wka_port->completion_wq); | ||
1590 | } | ||
1591 | |||
1592 | /** | ||
1593 | * zfcp_fsf_open_wka_port - create and send open wka-port request | ||
1594 | * @wka_port: pointer to struct zfcp_wka_port | ||
1595 | * Returns: 0 on success, error otherwise | ||
1596 | */ | ||
1597 | int zfcp_fsf_open_wka_port(struct zfcp_wka_port *wka_port) | ||
1598 | { | ||
1599 | struct qdio_buffer_element *sbale; | ||
1600 | struct zfcp_adapter *adapter = wka_port->adapter; | ||
1601 | struct zfcp_fsf_req *req; | ||
1602 | int retval = -EIO; | ||
1603 | |||
1604 | spin_lock_bh(&adapter->req_q.lock); | ||
1605 | if (zfcp_fsf_req_sbal_get(adapter)) | ||
1606 | goto out; | ||
1607 | |||
1608 | req = zfcp_fsf_req_create(adapter, | ||
1609 | FSF_QTCB_OPEN_PORT_WITH_DID, | ||
1610 | ZFCP_REQ_AUTO_CLEANUP, | ||
1611 | adapter->pool.fsf_req_erp); | ||
1612 | if (unlikely(IS_ERR(req))) { | ||
1613 | retval = PTR_ERR(req); | ||
1614 | goto out; | ||
1615 | } | ||
1616 | |||
1617 | sbale = zfcp_qdio_sbale_req(req); | ||
1618 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; | ||
1619 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; | ||
1620 | |||
1621 | req->handler = zfcp_fsf_open_wka_port_handler; | ||
1622 | req->qtcb->bottom.support.d_id = wka_port->d_id; | ||
1623 | req->data = wka_port; | ||
1624 | |||
1625 | zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); | ||
1626 | retval = zfcp_fsf_req_send(req); | ||
1627 | if (retval) | ||
1628 | zfcp_fsf_req_free(req); | ||
1629 | out: | ||
1630 | spin_unlock_bh(&adapter->req_q.lock); | ||
1631 | return retval; | ||
1632 | } | ||
1633 | |||
1634 | static void zfcp_fsf_close_wka_port_handler(struct zfcp_fsf_req *req) | ||
1635 | { | ||
1636 | struct zfcp_wka_port *wka_port = req->data; | ||
1637 | |||
1638 | if (req->qtcb->header.fsf_status == FSF_PORT_HANDLE_NOT_VALID) { | ||
1639 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | ||
1640 | zfcp_erp_adapter_reopen(wka_port->adapter, 0, 107, req); | ||
1641 | } | ||
1642 | |||
1643 | wka_port->status = ZFCP_WKA_PORT_OFFLINE; | ||
1644 | wake_up(&wka_port->completion_wq); | ||
1645 | } | ||
1646 | |||
1647 | /** | ||
1648 | * zfcp_fsf_close_wka_port - create and send close wka port request | ||
1649 | * @erp_action: pointer to struct zfcp_erp_action | ||
1650 | * Returns: 0 on success, error otherwise | ||
1651 | */ | ||
1652 | int zfcp_fsf_close_wka_port(struct zfcp_wka_port *wka_port) | ||
1653 | { | ||
1654 | struct qdio_buffer_element *sbale; | ||
1655 | struct zfcp_adapter *adapter = wka_port->adapter; | ||
1656 | struct zfcp_fsf_req *req; | ||
1657 | int retval = -EIO; | ||
1658 | |||
1659 | spin_lock_bh(&adapter->req_q.lock); | ||
1660 | if (zfcp_fsf_req_sbal_get(adapter)) | ||
1661 | goto out; | ||
1662 | |||
1663 | req = zfcp_fsf_req_create(adapter, FSF_QTCB_CLOSE_PORT, | ||
1664 | ZFCP_REQ_AUTO_CLEANUP, | ||
1665 | adapter->pool.fsf_req_erp); | ||
1666 | if (unlikely(IS_ERR(req))) { | ||
1667 | retval = PTR_ERR(req); | ||
1668 | goto out; | ||
1669 | } | ||
1670 | |||
1671 | sbale = zfcp_qdio_sbale_req(req); | ||
1672 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; | ||
1673 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; | ||
1674 | |||
1675 | req->handler = zfcp_fsf_close_wka_port_handler; | ||
1676 | req->data = wka_port; | ||
1677 | req->qtcb->header.port_handle = wka_port->handle; | ||
1678 | |||
1679 | zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); | ||
1680 | retval = zfcp_fsf_req_send(req); | ||
1681 | if (retval) | ||
1682 | zfcp_fsf_req_free(req); | ||
1683 | out: | ||
1684 | spin_unlock_bh(&adapter->req_q.lock); | ||
1685 | return retval; | ||
1686 | } | ||
1687 | |||
1571 | static void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req) | 1688 | static void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req) |
1572 | { | 1689 | { |
1573 | struct zfcp_port *port = req->data; | 1690 | struct zfcp_port *port = req->data; |