diff options
Diffstat (limited to 'drivers/s390/scsi/zfcp_fsf.c')
-rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 77 |
1 files changed, 44 insertions, 33 deletions
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 9c72e083559d..e6416f8541b0 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c | |||
@@ -644,38 +644,38 @@ static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req) | |||
644 | } | 644 | } |
645 | } | 645 | } |
646 | 646 | ||
647 | static int zfcp_fsf_sbal_check(struct zfcp_adapter *adapter) | 647 | static int zfcp_fsf_sbal_available(struct zfcp_adapter *adapter) |
648 | { | 648 | { |
649 | struct zfcp_qdio_queue *req_q = &adapter->req_q; | 649 | if (atomic_read(&adapter->req_q.count) > 0) |
650 | |||
651 | spin_lock_bh(&adapter->req_q_lock); | ||
652 | if (atomic_read(&req_q->count)) | ||
653 | return 1; | 650 | return 1; |
654 | spin_unlock_bh(&adapter->req_q_lock); | 651 | atomic_inc(&adapter->qdio_outb_full); |
655 | return 0; | 652 | return 0; |
656 | } | 653 | } |
657 | 654 | ||
658 | static int zfcp_fsf_sbal_available(struct zfcp_adapter *adapter) | ||
659 | { | ||
660 | unsigned int count = atomic_read(&adapter->req_q.count); | ||
661 | if (!count) | ||
662 | atomic_inc(&adapter->qdio_outb_full); | ||
663 | return count > 0; | ||
664 | } | ||
665 | |||
666 | static int zfcp_fsf_req_sbal_get(struct zfcp_adapter *adapter) | 655 | static int zfcp_fsf_req_sbal_get(struct zfcp_adapter *adapter) |
656 | __releases(&adapter->req_q_lock) | ||
657 | __acquires(&adapter->req_q_lock) | ||
667 | { | 658 | { |
659 | struct zfcp_qdio_queue *req_q = &adapter->req_q; | ||
668 | long ret; | 660 | long ret; |
669 | 661 | ||
662 | if (atomic_read(&req_q->count) <= -REQUEST_LIST_SIZE) | ||
663 | return -EIO; | ||
664 | if (atomic_read(&req_q->count) > 0) | ||
665 | return 0; | ||
666 | |||
667 | atomic_dec(&req_q->count); | ||
670 | spin_unlock_bh(&adapter->req_q_lock); | 668 | spin_unlock_bh(&adapter->req_q_lock); |
671 | ret = wait_event_interruptible_timeout(adapter->request_wq, | 669 | ret = wait_event_interruptible_timeout(adapter->request_wq, |
672 | zfcp_fsf_sbal_check(adapter), 5 * HZ); | 670 | atomic_read(&req_q->count) >= 0, |
671 | 5 * HZ); | ||
672 | spin_lock_bh(&adapter->req_q_lock); | ||
673 | atomic_inc(&req_q->count); | ||
674 | |||
673 | if (ret > 0) | 675 | if (ret > 0) |
674 | return 0; | 676 | return 0; |
675 | if (!ret) | 677 | if (!ret) |
676 | atomic_inc(&adapter->qdio_outb_full); | 678 | atomic_inc(&adapter->qdio_outb_full); |
677 | |||
678 | spin_lock_bh(&adapter->req_q_lock); | ||
679 | return -EIO; | 679 | return -EIO; |
680 | } | 680 | } |
681 | 681 | ||
@@ -1013,12 +1013,29 @@ skip_fsfstatus: | |||
1013 | send_ct->handler(send_ct->handler_data); | 1013 | send_ct->handler(send_ct->handler_data); |
1014 | } | 1014 | } |
1015 | 1015 | ||
1016 | static int zfcp_fsf_setup_sbals(struct zfcp_fsf_req *req, | 1016 | static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req, |
1017 | struct scatterlist *sg_req, | 1017 | struct scatterlist *sg_req, |
1018 | struct scatterlist *sg_resp, int max_sbals) | 1018 | struct scatterlist *sg_resp, |
1019 | int max_sbals) | ||
1019 | { | 1020 | { |
1021 | struct qdio_buffer_element *sbale = zfcp_qdio_sbale_req(req); | ||
1022 | u32 feat = req->adapter->adapter_features; | ||
1020 | int bytes; | 1023 | int bytes; |
1021 | 1024 | ||
1025 | if (!(feat & FSF_FEATURE_ELS_CT_CHAINED_SBALS)) { | ||
1026 | if (sg_req->length > PAGE_SIZE || sg_resp->length > PAGE_SIZE || | ||
1027 | !sg_is_last(sg_req) || !sg_is_last(sg_resp)) | ||
1028 | return -EOPNOTSUPP; | ||
1029 | |||
1030 | sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE_READ; | ||
1031 | sbale[2].addr = sg_virt(sg_req); | ||
1032 | sbale[2].length = sg_req->length; | ||
1033 | sbale[3].addr = sg_virt(sg_resp); | ||
1034 | sbale[3].length = sg_resp->length; | ||
1035 | sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY; | ||
1036 | return 0; | ||
1037 | } | ||
1038 | |||
1022 | bytes = zfcp_qdio_sbals_from_sg(req, SBAL_FLAGS0_TYPE_WRITE_READ, | 1039 | bytes = zfcp_qdio_sbals_from_sg(req, SBAL_FLAGS0_TYPE_WRITE_READ, |
1023 | sg_req, max_sbals); | 1040 | sg_req, max_sbals); |
1024 | if (bytes <= 0) | 1041 | if (bytes <= 0) |
@@ -1060,8 +1077,8 @@ int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool, | |||
1060 | goto out; | 1077 | goto out; |
1061 | } | 1078 | } |
1062 | 1079 | ||
1063 | ret = zfcp_fsf_setup_sbals(req, ct->req, ct->resp, | 1080 | ret = zfcp_fsf_setup_ct_els_sbals(req, ct->req, ct->resp, |
1064 | FSF_MAX_SBALS_PER_REQ); | 1081 | FSF_MAX_SBALS_PER_REQ); |
1065 | if (ret) | 1082 | if (ret) |
1066 | goto failed_send; | 1083 | goto failed_send; |
1067 | 1084 | ||
@@ -1171,7 +1188,7 @@ int zfcp_fsf_send_els(struct zfcp_send_els *els) | |||
1171 | goto out; | 1188 | goto out; |
1172 | } | 1189 | } |
1173 | 1190 | ||
1174 | ret = zfcp_fsf_setup_sbals(req, els->req, els->resp, 2); | 1191 | ret = zfcp_fsf_setup_ct_els_sbals(req, els->req, els->resp, 2); |
1175 | 1192 | ||
1176 | if (ret) | 1193 | if (ret) |
1177 | goto failed_send; | 1194 | goto failed_send; |
@@ -1406,13 +1423,7 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req) | |||
1406 | switch (header->fsf_status_qual.word[0]) { | 1423 | switch (header->fsf_status_qual.word[0]) { |
1407 | case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: | 1424 | case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: |
1408 | case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: | 1425 | case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: |
1409 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | ||
1410 | break; | ||
1411 | case FSF_SQ_NO_RETRY_POSSIBLE: | 1426 | case FSF_SQ_NO_RETRY_POSSIBLE: |
1412 | dev_warn(&req->adapter->ccw_device->dev, | ||
1413 | "Remote port 0x%016Lx could not be opened\n", | ||
1414 | (unsigned long long)port->wwpn); | ||
1415 | zfcp_erp_port_failed(port, 32, req); | ||
1416 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 1427 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
1417 | break; | 1428 | break; |
1418 | } | 1429 | } |
@@ -1440,10 +1451,10 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req) | |||
1440 | * Alternately, an ADISC/PDISC ELS should suffice, as well. | 1451 | * Alternately, an ADISC/PDISC ELS should suffice, as well. |
1441 | */ | 1452 | */ |
1442 | plogi = (struct fsf_plogi *) req->qtcb->bottom.support.els; | 1453 | plogi = (struct fsf_plogi *) req->qtcb->bottom.support.els; |
1443 | if (req->qtcb->bottom.support.els1_length >= sizeof(*plogi)) { | 1454 | if (req->qtcb->bottom.support.els1_length >= |
1455 | FSF_PLOGI_MIN_LEN) { | ||
1444 | if (plogi->serv_param.wwpn != port->wwpn) | 1456 | if (plogi->serv_param.wwpn != port->wwpn) |
1445 | atomic_clear_mask(ZFCP_STATUS_PORT_DID_DID, | 1457 | port->d_id = 0; |
1446 | &port->status); | ||
1447 | else { | 1458 | else { |
1448 | port->wwnn = plogi->serv_param.wwnn; | 1459 | port->wwnn = plogi->serv_param.wwnn; |
1449 | zfcp_fc_plogi_evaluate(port, plogi); | 1460 | zfcp_fc_plogi_evaluate(port, plogi); |
@@ -1907,7 +1918,7 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req) | |||
1907 | dev_err(&adapter->ccw_device->dev, | 1918 | dev_err(&adapter->ccw_device->dev, |
1908 | "Shared read-write access not " | 1919 | "Shared read-write access not " |
1909 | "supported (unit 0x%016Lx, port " | 1920 | "supported (unit 0x%016Lx, port " |
1910 | "0x%016Lx\n)", | 1921 | "0x%016Lx)\n", |
1911 | (unsigned long long)unit->fcp_lun, | 1922 | (unsigned long long)unit->fcp_lun, |
1912 | (unsigned long long)unit->port->wwpn); | 1923 | (unsigned long long)unit->port->wwpn); |
1913 | zfcp_erp_unit_failed(unit, 36, req); | 1924 | zfcp_erp_unit_failed(unit, 36, req); |