diff options
Diffstat (limited to 'drivers/s390/scsi/zfcp_fsf.c')
-rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 56 |
1 files changed, 38 insertions, 18 deletions
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index c57658f3d34f..47795fbf081f 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c | |||
@@ -670,8 +670,11 @@ static int zfcp_fsf_req_sbal_get(struct zfcp_adapter *adapter) | |||
670 | zfcp_fsf_sbal_check(adapter), 5 * HZ); | 670 | zfcp_fsf_sbal_check(adapter), 5 * HZ); |
671 | if (ret > 0) | 671 | if (ret > 0) |
672 | return 0; | 672 | return 0; |
673 | if (!ret) | 673 | if (!ret) { |
674 | atomic_inc(&adapter->qdio_outb_full); | 674 | atomic_inc(&adapter->qdio_outb_full); |
675 | /* assume hanging outbound queue, try queue recovery */ | ||
676 | zfcp_erp_adapter_reopen(adapter, 0, "fsrsg_1", NULL); | ||
677 | } | ||
675 | 678 | ||
676 | spin_lock_bh(&adapter->req_q_lock); | 679 | spin_lock_bh(&adapter->req_q_lock); |
677 | return -EIO; | 680 | return -EIO; |
@@ -722,7 +725,7 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_adapter *adapter, | |||
722 | req = zfcp_fsf_alloc_qtcb(pool); | 725 | req = zfcp_fsf_alloc_qtcb(pool); |
723 | 726 | ||
724 | if (unlikely(!req)) | 727 | if (unlikely(!req)) |
725 | return ERR_PTR(-EIO); | 728 | return ERR_PTR(-ENOMEM); |
726 | 729 | ||
727 | if (adapter->req_no == 0) | 730 | if (adapter->req_no == 0) |
728 | adapter->req_no++; | 731 | adapter->req_no++; |
@@ -1010,6 +1013,23 @@ skip_fsfstatus: | |||
1010 | send_ct->handler(send_ct->handler_data); | 1013 | send_ct->handler(send_ct->handler_data); |
1011 | } | 1014 | } |
1012 | 1015 | ||
1016 | static void zfcp_fsf_setup_ct_els_unchained(struct qdio_buffer_element *sbale, | ||
1017 | struct scatterlist *sg_req, | ||
1018 | struct scatterlist *sg_resp) | ||
1019 | { | ||
1020 | sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE_READ; | ||
1021 | sbale[2].addr = sg_virt(sg_req); | ||
1022 | sbale[2].length = sg_req->length; | ||
1023 | sbale[3].addr = sg_virt(sg_resp); | ||
1024 | sbale[3].length = sg_resp->length; | ||
1025 | sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY; | ||
1026 | } | ||
1027 | |||
1028 | static int zfcp_fsf_one_sbal(struct scatterlist *sg) | ||
1029 | { | ||
1030 | return sg_is_last(sg) && sg->length <= PAGE_SIZE; | ||
1031 | } | ||
1032 | |||
1013 | static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req, | 1033 | static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req, |
1014 | struct scatterlist *sg_req, | 1034 | struct scatterlist *sg_req, |
1015 | struct scatterlist *sg_resp, | 1035 | struct scatterlist *sg_resp, |
@@ -1020,30 +1040,30 @@ static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req, | |||
1020 | int bytes; | 1040 | int bytes; |
1021 | 1041 | ||
1022 | if (!(feat & FSF_FEATURE_ELS_CT_CHAINED_SBALS)) { | 1042 | if (!(feat & FSF_FEATURE_ELS_CT_CHAINED_SBALS)) { |
1023 | if (sg_req->length > PAGE_SIZE || sg_resp->length > PAGE_SIZE || | 1043 | if (!zfcp_fsf_one_sbal(sg_req) || !zfcp_fsf_one_sbal(sg_resp)) |
1024 | !sg_is_last(sg_req) || !sg_is_last(sg_resp)) | ||
1025 | return -EOPNOTSUPP; | 1044 | return -EOPNOTSUPP; |
1026 | 1045 | ||
1027 | sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE_READ; | 1046 | zfcp_fsf_setup_ct_els_unchained(sbale, sg_req, sg_resp); |
1028 | sbale[2].addr = sg_virt(sg_req); | 1047 | return 0; |
1029 | sbale[2].length = sg_req->length; | 1048 | } |
1030 | sbale[3].addr = sg_virt(sg_resp); | 1049 | |
1031 | sbale[3].length = sg_resp->length; | 1050 | /* use single, unchained SBAL if it can hold the request */ |
1032 | sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY; | 1051 | if (zfcp_fsf_one_sbal(sg_req) && zfcp_fsf_one_sbal(sg_resp)) { |
1052 | zfcp_fsf_setup_ct_els_unchained(sbale, sg_req, sg_resp); | ||
1033 | return 0; | 1053 | return 0; |
1034 | } | 1054 | } |
1035 | 1055 | ||
1036 | bytes = zfcp_qdio_sbals_from_sg(req, SBAL_FLAGS0_TYPE_WRITE_READ, | 1056 | bytes = zfcp_qdio_sbals_from_sg(req, SBAL_FLAGS0_TYPE_WRITE_READ, |
1037 | sg_req, max_sbals); | 1057 | sg_req, max_sbals); |
1038 | if (bytes <= 0) | 1058 | if (bytes <= 0) |
1039 | return -ENOMEM; | 1059 | return -EIO; |
1040 | req->qtcb->bottom.support.req_buf_length = bytes; | 1060 | req->qtcb->bottom.support.req_buf_length = bytes; |
1041 | req->sbale_curr = ZFCP_LAST_SBALE_PER_SBAL; | 1061 | req->sbale_curr = ZFCP_LAST_SBALE_PER_SBAL; |
1042 | 1062 | ||
1043 | bytes = zfcp_qdio_sbals_from_sg(req, SBAL_FLAGS0_TYPE_WRITE_READ, | 1063 | bytes = zfcp_qdio_sbals_from_sg(req, SBAL_FLAGS0_TYPE_WRITE_READ, |
1044 | sg_resp, max_sbals); | 1064 | sg_resp, max_sbals); |
1045 | if (bytes <= 0) | 1065 | if (bytes <= 0) |
1046 | return -ENOMEM; | 1066 | return -EIO; |
1047 | req->qtcb->bottom.support.resp_buf_length = bytes; | 1067 | req->qtcb->bottom.support.resp_buf_length = bytes; |
1048 | 1068 | ||
1049 | return 0; | 1069 | return 0; |
@@ -1607,10 +1627,10 @@ static void zfcp_fsf_open_wka_port_handler(struct zfcp_fsf_req *req) | |||
1607 | case FSF_ACCESS_DENIED: | 1627 | case FSF_ACCESS_DENIED: |
1608 | wka_port->status = ZFCP_WKA_PORT_OFFLINE; | 1628 | wka_port->status = ZFCP_WKA_PORT_OFFLINE; |
1609 | break; | 1629 | break; |
1610 | case FSF_PORT_ALREADY_OPEN: | ||
1611 | break; | ||
1612 | case FSF_GOOD: | 1630 | case FSF_GOOD: |
1613 | wka_port->handle = header->port_handle; | 1631 | wka_port->handle = header->port_handle; |
1632 | /* fall through */ | ||
1633 | case FSF_PORT_ALREADY_OPEN: | ||
1614 | wka_port->status = ZFCP_WKA_PORT_ONLINE; | 1634 | wka_port->status = ZFCP_WKA_PORT_ONLINE; |
1615 | } | 1635 | } |
1616 | out: | 1636 | out: |
@@ -1731,15 +1751,16 @@ static void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req) | |||
1731 | zfcp_fsf_access_denied_port(req, port); | 1751 | zfcp_fsf_access_denied_port(req, port); |
1732 | break; | 1752 | break; |
1733 | case FSF_PORT_BOXED: | 1753 | case FSF_PORT_BOXED: |
1734 | zfcp_erp_port_boxed(port, "fscpph2", req); | ||
1735 | req->status |= ZFCP_STATUS_FSFREQ_ERROR | | ||
1736 | ZFCP_STATUS_FSFREQ_RETRY; | ||
1737 | /* can't use generic zfcp_erp_modify_port_status because | 1754 | /* can't use generic zfcp_erp_modify_port_status because |
1738 | * ZFCP_STATUS_COMMON_OPEN must not be reset for the port */ | 1755 | * ZFCP_STATUS_COMMON_OPEN must not be reset for the port */ |
1739 | atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status); | 1756 | atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status); |
1740 | list_for_each_entry(unit, &port->unit_list_head, list) | 1757 | list_for_each_entry(unit, &port->unit_list_head, list) |
1741 | atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, | 1758 | atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, |
1742 | &unit->status); | 1759 | &unit->status); |
1760 | zfcp_erp_port_boxed(port, "fscpph2", req); | ||
1761 | req->status |= ZFCP_STATUS_FSFREQ_ERROR | | ||
1762 | ZFCP_STATUS_FSFREQ_RETRY; | ||
1763 | |||
1743 | break; | 1764 | break; |
1744 | case FSF_ADAPTER_STATUS_AVAILABLE: | 1765 | case FSF_ADAPTER_STATUS_AVAILABLE: |
1745 | switch (header->fsf_status_qual.word[0]) { | 1766 | switch (header->fsf_status_qual.word[0]) { |
@@ -2541,7 +2562,6 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter, | |||
2541 | bytes = zfcp_qdio_sbals_from_sg(req, direction, fsf_cfdc->sg, | 2562 | bytes = zfcp_qdio_sbals_from_sg(req, direction, fsf_cfdc->sg, |
2542 | FSF_MAX_SBALS_PER_REQ); | 2563 | FSF_MAX_SBALS_PER_REQ); |
2543 | if (bytes != ZFCP_CFDC_MAX_SIZE) { | 2564 | if (bytes != ZFCP_CFDC_MAX_SIZE) { |
2544 | retval = -ENOMEM; | ||
2545 | zfcp_fsf_req_free(req); | 2565 | zfcp_fsf_req_free(req); |
2546 | goto out; | 2566 | goto out; |
2547 | } | 2567 | } |