diff options
| -rw-r--r-- | drivers/s390/scsi/zfcp_erp.c | 68 | ||||
| -rw-r--r-- | drivers/s390/scsi/zfcp_fc.c | 8 | ||||
| -rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 56 | ||||
| -rw-r--r-- | drivers/s390/scsi/zfcp_scsi.c | 25 | ||||
| -rw-r--r-- | drivers/s390/scsi/zfcp_sysfs.c | 7 | ||||
| -rw-r--r-- | drivers/scsi/libfc/fc_exch.c | 23 | ||||
| -rw-r--r-- | drivers/scsi/libiscsi.c | 4 | ||||
| -rw-r--r-- | drivers/scsi/libsas/sas_expander.c | 147 | ||||
| -rw-r--r-- | drivers/scsi/libsas/sas_port.c | 19 | ||||
| -rw-r--r-- | drivers/scsi/qla4xxx/ql4_dbg.c | 15 | ||||
| -rw-r--r-- | drivers/scsi/qla4xxx/ql4_def.h | 9 | ||||
| -rw-r--r-- | drivers/scsi/qla4xxx/ql4_fw.h | 7 | ||||
| -rw-r--r-- | drivers/scsi/qla4xxx/ql4_iocb.c | 133 | ||||
| -rw-r--r-- | drivers/scsi/qla4xxx/ql4_isr.c | 145 | ||||
| -rw-r--r-- | drivers/scsi/qla4xxx/ql4_mbx.c | 10 | ||||
| -rw-r--r-- | drivers/scsi/qla4xxx/ql4_os.c | 40 | ||||
| -rw-r--r-- | drivers/scsi/qla4xxx/ql4_version.h | 2 | ||||
| -rw-r--r-- | drivers/scsi/sd.c | 20 |
18 files changed, 465 insertions, 273 deletions
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 8030e25152fb..c75d6f35cb5f 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c | |||
| @@ -553,40 +553,35 @@ static void _zfcp_erp_unit_reopen_all(struct zfcp_port *port, int clear, | |||
| 553 | _zfcp_erp_unit_reopen(unit, clear, id, ref); | 553 | _zfcp_erp_unit_reopen(unit, clear, id, ref); |
| 554 | } | 554 | } |
| 555 | 555 | ||
| 556 | static void zfcp_erp_strategy_followup_actions(struct zfcp_erp_action *act) | 556 | static void zfcp_erp_strategy_followup_failed(struct zfcp_erp_action *act) |
| 557 | { | 557 | { |
| 558 | struct zfcp_adapter *adapter = act->adapter; | ||
| 559 | struct zfcp_port *port = act->port; | ||
| 560 | struct zfcp_unit *unit = act->unit; | ||
| 561 | u32 status = act->status; | ||
| 562 | |||
| 563 | /* initiate follow-up actions depending on success of finished action */ | ||
| 564 | switch (act->action) { | 558 | switch (act->action) { |
| 565 | |||
| 566 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: | 559 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: |
| 567 | if (status == ZFCP_ERP_SUCCEEDED) | 560 | _zfcp_erp_adapter_reopen(act->adapter, 0, "ersff_1", NULL); |
| 568 | _zfcp_erp_port_reopen_all(adapter, 0, "ersfa_1", NULL); | ||
| 569 | else | ||
| 570 | _zfcp_erp_adapter_reopen(adapter, 0, "ersfa_2", NULL); | ||
| 571 | break; | 561 | break; |
| 572 | |||
| 573 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | 562 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: |
| 574 | if (status == ZFCP_ERP_SUCCEEDED) | 563 | _zfcp_erp_port_forced_reopen(act->port, 0, "ersff_2", NULL); |
| 575 | _zfcp_erp_port_reopen(port, 0, "ersfa_3", NULL); | ||
| 576 | else | ||
| 577 | _zfcp_erp_adapter_reopen(adapter, 0, "ersfa_4", NULL); | ||
| 578 | break; | 564 | break; |
| 579 | |||
| 580 | case ZFCP_ERP_ACTION_REOPEN_PORT: | 565 | case ZFCP_ERP_ACTION_REOPEN_PORT: |
| 581 | if (status == ZFCP_ERP_SUCCEEDED) | 566 | _zfcp_erp_port_reopen(act->port, 0, "ersff_3", NULL); |
| 582 | _zfcp_erp_unit_reopen_all(port, 0, "ersfa_5", NULL); | ||
| 583 | else | ||
| 584 | _zfcp_erp_port_forced_reopen(port, 0, "ersfa_6", NULL); | ||
| 585 | break; | 567 | break; |
| 586 | |||
| 587 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | 568 | case ZFCP_ERP_ACTION_REOPEN_UNIT: |
| 588 | if (status != ZFCP_ERP_SUCCEEDED) | 569 | _zfcp_erp_unit_reopen(act->unit, 0, "ersff_4", NULL); |
| 589 | _zfcp_erp_port_reopen(unit->port, 0, "ersfa_7", NULL); | 570 | break; |
| 571 | } | ||
| 572 | } | ||
| 573 | |||
| 574 | static void zfcp_erp_strategy_followup_success(struct zfcp_erp_action *act) | ||
| 575 | { | ||
| 576 | switch (act->action) { | ||
| 577 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: | ||
| 578 | _zfcp_erp_port_reopen_all(act->adapter, 0, "ersfs_1", NULL); | ||
| 579 | break; | ||
| 580 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | ||
| 581 | _zfcp_erp_port_reopen(act->port, 0, "ersfs_2", NULL); | ||
| 582 | break; | ||
| 583 | case ZFCP_ERP_ACTION_REOPEN_PORT: | ||
| 584 | _zfcp_erp_unit_reopen_all(act->port, 0, "ersfs_3", NULL); | ||
| 590 | break; | 585 | break; |
| 591 | } | 586 | } |
| 592 | } | 587 | } |
| @@ -801,7 +796,7 @@ static int zfcp_erp_port_forced_strategy(struct zfcp_erp_action *erp_action) | |||
| 801 | return ZFCP_ERP_FAILED; | 796 | return ZFCP_ERP_FAILED; |
| 802 | 797 | ||
| 803 | case ZFCP_ERP_STEP_PHYS_PORT_CLOSING: | 798 | case ZFCP_ERP_STEP_PHYS_PORT_CLOSING: |
| 804 | if (status & ZFCP_STATUS_PORT_PHYS_OPEN) | 799 | if (!(status & ZFCP_STATUS_PORT_PHYS_OPEN)) |
| 805 | return ZFCP_ERP_SUCCEEDED; | 800 | return ZFCP_ERP_SUCCEEDED; |
| 806 | } | 801 | } |
| 807 | return ZFCP_ERP_FAILED; | 802 | return ZFCP_ERP_FAILED; |
| @@ -853,11 +848,17 @@ void zfcp_erp_port_strategy_open_lookup(struct work_struct *work) | |||
| 853 | gid_pn_work); | 848 | gid_pn_work); |
| 854 | 849 | ||
| 855 | retval = zfcp_fc_ns_gid_pn(&port->erp_action); | 850 | retval = zfcp_fc_ns_gid_pn(&port->erp_action); |
| 856 | if (retval == -ENOMEM) | 851 | if (!retval) { |
| 857 | zfcp_erp_notify(&port->erp_action, ZFCP_ERP_NOMEM); | 852 | port->erp_action.step = ZFCP_ERP_STEP_NAMESERVER_LOOKUP; |
| 858 | port->erp_action.step = ZFCP_ERP_STEP_NAMESERVER_LOOKUP; | 853 | goto out; |
| 859 | if (retval) | 854 | } |
| 860 | zfcp_erp_notify(&port->erp_action, ZFCP_ERP_FAILED); | 855 | if (retval == -ENOMEM) { |
| 856 | zfcp_erp_notify(&port->erp_action, ZFCP_STATUS_ERP_LOWMEM); | ||
| 857 | goto out; | ||
| 858 | } | ||
| 859 | /* all other error condtions */ | ||
| 860 | zfcp_erp_notify(&port->erp_action, 0); | ||
| 861 | out: | ||
| 861 | zfcp_port_put(port); | 862 | zfcp_port_put(port); |
| 862 | } | 863 | } |
| 863 | 864 | ||
| @@ -1289,7 +1290,10 @@ static int zfcp_erp_strategy(struct zfcp_erp_action *erp_action) | |||
| 1289 | retval = zfcp_erp_strategy_statechange(erp_action, retval); | 1290 | retval = zfcp_erp_strategy_statechange(erp_action, retval); |
| 1290 | if (retval == ZFCP_ERP_EXIT) | 1291 | if (retval == ZFCP_ERP_EXIT) |
| 1291 | goto unlock; | 1292 | goto unlock; |
| 1292 | zfcp_erp_strategy_followup_actions(erp_action); | 1293 | if (retval == ZFCP_ERP_SUCCEEDED) |
| 1294 | zfcp_erp_strategy_followup_success(erp_action); | ||
| 1295 | if (retval == ZFCP_ERP_FAILED) | ||
| 1296 | zfcp_erp_strategy_followup_failed(erp_action); | ||
| 1293 | 1297 | ||
| 1294 | unlock: | 1298 | unlock: |
| 1295 | write_unlock(&adapter->erp_lock); | 1299 | write_unlock(&adapter->erp_lock); |
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index 2f0705d76b72..47daebfa7e59 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c | |||
| @@ -79,11 +79,9 @@ static int zfcp_wka_port_get(struct zfcp_wka_port *wka_port) | |||
| 79 | 79 | ||
| 80 | mutex_unlock(&wka_port->mutex); | 80 | mutex_unlock(&wka_port->mutex); |
| 81 | 81 | ||
| 82 | wait_event_timeout( | 82 | wait_event(wka_port->completion_wq, |
| 83 | wka_port->completion_wq, | 83 | wka_port->status == ZFCP_WKA_PORT_ONLINE || |
| 84 | wka_port->status == ZFCP_WKA_PORT_ONLINE || | 84 | wka_port->status == ZFCP_WKA_PORT_OFFLINE); |
| 85 | wka_port->status == ZFCP_WKA_PORT_OFFLINE, | ||
| 86 | HZ >> 1); | ||
| 87 | 85 | ||
| 88 | if (wka_port->status == ZFCP_WKA_PORT_ONLINE) { | 86 | if (wka_port->status == ZFCP_WKA_PORT_ONLINE) { |
| 89 | atomic_inc(&wka_port->refcount); | 87 | atomic_inc(&wka_port->refcount); |
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 | } |
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 967ede73f4c5..6925a1784682 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c | |||
| @@ -167,20 +167,21 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) | |||
| 167 | struct zfcp_unit *unit = scpnt->device->hostdata; | 167 | struct zfcp_unit *unit = scpnt->device->hostdata; |
| 168 | struct zfcp_fsf_req *old_req, *abrt_req; | 168 | struct zfcp_fsf_req *old_req, *abrt_req; |
| 169 | unsigned long flags; | 169 | unsigned long flags; |
| 170 | unsigned long old_req_id = (unsigned long) scpnt->host_scribble; | 170 | unsigned long old_reqid = (unsigned long) scpnt->host_scribble; |
| 171 | int retval = SUCCESS; | 171 | int retval = SUCCESS; |
| 172 | int retry = 3; | 172 | int retry = 3; |
| 173 | char *dbf_tag; | ||
| 173 | 174 | ||
| 174 | /* avoid race condition between late normal completion and abort */ | 175 | /* avoid race condition between late normal completion and abort */ |
| 175 | write_lock_irqsave(&adapter->abort_lock, flags); | 176 | write_lock_irqsave(&adapter->abort_lock, flags); |
| 176 | 177 | ||
| 177 | spin_lock(&adapter->req_list_lock); | 178 | spin_lock(&adapter->req_list_lock); |
| 178 | old_req = zfcp_reqlist_find(adapter, old_req_id); | 179 | old_req = zfcp_reqlist_find(adapter, old_reqid); |
| 179 | spin_unlock(&adapter->req_list_lock); | 180 | spin_unlock(&adapter->req_list_lock); |
| 180 | if (!old_req) { | 181 | if (!old_req) { |
| 181 | write_unlock_irqrestore(&adapter->abort_lock, flags); | 182 | write_unlock_irqrestore(&adapter->abort_lock, flags); |
| 182 | zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL, | 183 | zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL, |
| 183 | old_req_id); | 184 | old_reqid); |
| 184 | return FAILED; /* completion could be in progress */ | 185 | return FAILED; /* completion could be in progress */ |
| 185 | } | 186 | } |
| 186 | old_req->data = NULL; | 187 | old_req->data = NULL; |
| @@ -189,7 +190,7 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) | |||
| 189 | write_unlock_irqrestore(&adapter->abort_lock, flags); | 190 | write_unlock_irqrestore(&adapter->abort_lock, flags); |
| 190 | 191 | ||
| 191 | while (retry--) { | 192 | while (retry--) { |
| 192 | abrt_req = zfcp_fsf_abort_fcp_command(old_req_id, unit); | 193 | abrt_req = zfcp_fsf_abort_fcp_command(old_reqid, unit); |
| 193 | if (abrt_req) | 194 | if (abrt_req) |
| 194 | break; | 195 | break; |
| 195 | 196 | ||
| @@ -197,7 +198,7 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) | |||
| 197 | if (!(atomic_read(&adapter->status) & | 198 | if (!(atomic_read(&adapter->status) & |
| 198 | ZFCP_STATUS_COMMON_RUNNING)) { | 199 | ZFCP_STATUS_COMMON_RUNNING)) { |
| 199 | zfcp_scsi_dbf_event_abort("nres", adapter, scpnt, NULL, | 200 | zfcp_scsi_dbf_event_abort("nres", adapter, scpnt, NULL, |
| 200 | old_req_id); | 201 | old_reqid); |
| 201 | return SUCCESS; | 202 | return SUCCESS; |
| 202 | } | 203 | } |
| 203 | } | 204 | } |
| @@ -208,13 +209,14 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) | |||
| 208 | abrt_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); | 209 | abrt_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); |
| 209 | 210 | ||
| 210 | if (abrt_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) | 211 | if (abrt_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) |
| 211 | zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, abrt_req, 0); | 212 | dbf_tag = "okay"; |
| 212 | else if (abrt_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) | 213 | else if (abrt_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) |
| 213 | zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, abrt_req, 0); | 214 | dbf_tag = "lte2"; |
| 214 | else { | 215 | else { |
| 215 | zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, abrt_req, 0); | 216 | dbf_tag = "fail"; |
| 216 | retval = FAILED; | 217 | retval = FAILED; |
| 217 | } | 218 | } |
| 219 | zfcp_scsi_dbf_event_abort(dbf_tag, adapter, scpnt, abrt_req, old_reqid); | ||
| 218 | zfcp_fsf_req_free(abrt_req); | 220 | zfcp_fsf_req_free(abrt_req); |
| 219 | return retval; | 221 | return retval; |
| 220 | } | 222 | } |
| @@ -534,6 +536,9 @@ static void zfcp_scsi_rport_register(struct zfcp_port *port) | |||
| 534 | struct fc_rport_identifiers ids; | 536 | struct fc_rport_identifiers ids; |
| 535 | struct fc_rport *rport; | 537 | struct fc_rport *rport; |
| 536 | 538 | ||
| 539 | if (port->rport) | ||
| 540 | return; | ||
| 541 | |||
| 537 | ids.node_name = port->wwnn; | 542 | ids.node_name = port->wwnn; |
| 538 | ids.port_name = port->wwpn; | 543 | ids.port_name = port->wwpn; |
| 539 | ids.port_id = port->d_id; | 544 | ids.port_id = port->d_id; |
| @@ -557,8 +562,10 @@ static void zfcp_scsi_rport_block(struct zfcp_port *port) | |||
| 557 | { | 562 | { |
| 558 | struct fc_rport *rport = port->rport; | 563 | struct fc_rport *rport = port->rport; |
| 559 | 564 | ||
| 560 | if (rport) | 565 | if (rport) { |
| 561 | fc_remote_port_delete(rport); | 566 | fc_remote_port_delete(rport); |
| 567 | port->rport = NULL; | ||
| 568 | } | ||
| 562 | } | 569 | } |
| 563 | 570 | ||
| 564 | void zfcp_scsi_schedule_rport_register(struct zfcp_port *port) | 571 | void zfcp_scsi_schedule_rport_register(struct zfcp_port *port) |
diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c index 3e51e64d1108..0fe5cce818cb 100644 --- a/drivers/s390/scsi/zfcp_sysfs.c +++ b/drivers/s390/scsi/zfcp_sysfs.c | |||
| @@ -494,9 +494,14 @@ static ssize_t zfcp_sysfs_adapter_q_full_show(struct device *dev, | |||
| 494 | struct Scsi_Host *scsi_host = class_to_shost(dev); | 494 | struct Scsi_Host *scsi_host = class_to_shost(dev); |
| 495 | struct zfcp_adapter *adapter = | 495 | struct zfcp_adapter *adapter = |
| 496 | (struct zfcp_adapter *) scsi_host->hostdata[0]; | 496 | (struct zfcp_adapter *) scsi_host->hostdata[0]; |
| 497 | u64 util; | ||
| 498 | |||
| 499 | spin_lock_bh(&adapter->qdio_stat_lock); | ||
| 500 | util = adapter->req_q_util; | ||
| 501 | spin_unlock_bh(&adapter->qdio_stat_lock); | ||
| 497 | 502 | ||
| 498 | return sprintf(buf, "%d %llu\n", atomic_read(&adapter->qdio_outb_full), | 503 | return sprintf(buf, "%d %llu\n", atomic_read(&adapter->qdio_outb_full), |
| 499 | (unsigned long long)adapter->req_q_util); | 504 | (unsigned long long)util); |
| 500 | } | 505 | } |
| 501 | static DEVICE_ATTR(queue_full, S_IRUGO, zfcp_sysfs_adapter_q_full_show, NULL); | 506 | static DEVICE_ATTR(queue_full, S_IRUGO, zfcp_sysfs_adapter_q_full_show, NULL); |
| 502 | 507 | ||
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 2bc22be5f849..145ab9ba55ea 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c | |||
| @@ -415,9 +415,9 @@ static void fc_exch_timeout(struct work_struct *work) | |||
| 415 | e_stat = ep->esb_stat; | 415 | e_stat = ep->esb_stat; |
| 416 | if (e_stat & ESB_ST_COMPLETE) { | 416 | if (e_stat & ESB_ST_COMPLETE) { |
| 417 | ep->esb_stat = e_stat & ~ESB_ST_REC_QUAL; | 417 | ep->esb_stat = e_stat & ~ESB_ST_REC_QUAL; |
| 418 | spin_unlock_bh(&ep->ex_lock); | ||
| 418 | if (e_stat & ESB_ST_REC_QUAL) | 419 | if (e_stat & ESB_ST_REC_QUAL) |
| 419 | fc_exch_rrq(ep); | 420 | fc_exch_rrq(ep); |
| 420 | spin_unlock_bh(&ep->ex_lock); | ||
| 421 | goto done; | 421 | goto done; |
| 422 | } else { | 422 | } else { |
| 423 | resp = ep->resp; | 423 | resp = ep->resp; |
| @@ -1624,14 +1624,14 @@ static void fc_exch_rrq(struct fc_exch *ep) | |||
| 1624 | struct fc_lport *lp; | 1624 | struct fc_lport *lp; |
| 1625 | struct fc_els_rrq *rrq; | 1625 | struct fc_els_rrq *rrq; |
| 1626 | struct fc_frame *fp; | 1626 | struct fc_frame *fp; |
| 1627 | struct fc_seq *rrq_sp; | ||
| 1628 | u32 did; | 1627 | u32 did; |
| 1629 | 1628 | ||
| 1630 | lp = ep->lp; | 1629 | lp = ep->lp; |
| 1631 | 1630 | ||
| 1632 | fp = fc_frame_alloc(lp, sizeof(*rrq)); | 1631 | fp = fc_frame_alloc(lp, sizeof(*rrq)); |
| 1633 | if (!fp) | 1632 | if (!fp) |
| 1634 | return; | 1633 | goto retry; |
| 1634 | |||
| 1635 | rrq = fc_frame_payload_get(fp, sizeof(*rrq)); | 1635 | rrq = fc_frame_payload_get(fp, sizeof(*rrq)); |
| 1636 | memset(rrq, 0, sizeof(*rrq)); | 1636 | memset(rrq, 0, sizeof(*rrq)); |
| 1637 | rrq->rrq_cmd = ELS_RRQ; | 1637 | rrq->rrq_cmd = ELS_RRQ; |
| @@ -1647,13 +1647,20 @@ static void fc_exch_rrq(struct fc_exch *ep) | |||
| 1647 | fc_host_port_id(lp->host), FC_TYPE_ELS, | 1647 | fc_host_port_id(lp->host), FC_TYPE_ELS, |
| 1648 | FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0); | 1648 | FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0); |
| 1649 | 1649 | ||
| 1650 | rrq_sp = fc_exch_seq_send(lp, fp, fc_exch_rrq_resp, NULL, ep, | 1650 | if (fc_exch_seq_send(lp, fp, fc_exch_rrq_resp, NULL, ep, lp->e_d_tov)) |
| 1651 | lp->e_d_tov); | 1651 | return; |
| 1652 | if (!rrq_sp) { | 1652 | |
| 1653 | ep->esb_stat |= ESB_ST_REC_QUAL; | 1653 | retry: |
| 1654 | fc_exch_timer_set_locked(ep, ep->r_a_tov); | 1654 | spin_lock_bh(&ep->ex_lock); |
| 1655 | if (ep->state & (FC_EX_RST_CLEANUP | FC_EX_DONE)) { | ||
| 1656 | spin_unlock_bh(&ep->ex_lock); | ||
| 1657 | /* drop hold for rec qual */ | ||
| 1658 | fc_exch_release(ep); | ||
| 1655 | return; | 1659 | return; |
| 1656 | } | 1660 | } |
| 1661 | ep->esb_stat |= ESB_ST_REC_QUAL; | ||
| 1662 | fc_exch_timer_set_locked(ep, ep->r_a_tov); | ||
| 1663 | spin_unlock_bh(&ep->ex_lock); | ||
| 1657 | } | 1664 | } |
| 1658 | 1665 | ||
| 1659 | 1666 | ||
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 716cc344c5df..a751f6230c22 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
| @@ -1974,10 +1974,10 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) | |||
| 1974 | * good and have never sent us a successful tmf response | 1974 | * good and have never sent us a successful tmf response |
| 1975 | * then sent more data for the cmd. | 1975 | * then sent more data for the cmd. |
| 1976 | */ | 1976 | */ |
| 1977 | spin_lock(&session->lock); | 1977 | spin_lock_bh(&session->lock); |
| 1978 | fail_scsi_task(task, DID_ABORT); | 1978 | fail_scsi_task(task, DID_ABORT); |
| 1979 | conn->tmf_state = TMF_INITIAL; | 1979 | conn->tmf_state = TMF_INITIAL; |
| 1980 | spin_unlock(&session->lock); | 1980 | spin_unlock_bh(&session->lock); |
| 1981 | iscsi_start_tx(conn); | 1981 | iscsi_start_tx(conn); |
| 1982 | goto success_unlocked; | 1982 | goto success_unlocked; |
| 1983 | case TMF_TIMEDOUT: | 1983 | case TMF_TIMEDOUT: |
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index 54fa1e42dc4d..b3381959acce 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c | |||
| @@ -766,6 +766,7 @@ static int sas_ex_join_wide_port(struct domain_device *parent, int phy_id) | |||
| 766 | if (!memcmp(phy->attached_sas_addr, ephy->attached_sas_addr, | 766 | if (!memcmp(phy->attached_sas_addr, ephy->attached_sas_addr, |
| 767 | SAS_ADDR_SIZE) && ephy->port) { | 767 | SAS_ADDR_SIZE) && ephy->port) { |
| 768 | sas_port_add_phy(ephy->port, phy->phy); | 768 | sas_port_add_phy(ephy->port, phy->phy); |
| 769 | phy->port = ephy->port; | ||
| 769 | phy->phy_state = PHY_DEVICE_DISCOVERED; | 770 | phy->phy_state = PHY_DEVICE_DISCOVERED; |
| 770 | return 0; | 771 | return 0; |
| 771 | } | 772 | } |
| @@ -945,11 +946,21 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id) | |||
| 945 | if (ex->ex_phy[i].phy_state == PHY_VACANT || | 946 | if (ex->ex_phy[i].phy_state == PHY_VACANT || |
| 946 | ex->ex_phy[i].phy_state == PHY_NOT_PRESENT) | 947 | ex->ex_phy[i].phy_state == PHY_NOT_PRESENT) |
| 947 | continue; | 948 | continue; |
| 948 | 949 | /* | |
| 950 | * Due to races, the phy might not get added to the | ||
| 951 | * wide port, so we add the phy to the wide port here. | ||
| 952 | */ | ||
| 949 | if (SAS_ADDR(ex->ex_phy[i].attached_sas_addr) == | 953 | if (SAS_ADDR(ex->ex_phy[i].attached_sas_addr) == |
| 950 | SAS_ADDR(child->sas_addr)) | 954 | SAS_ADDR(child->sas_addr)) { |
| 951 | ex->ex_phy[i].phy_state= PHY_DEVICE_DISCOVERED; | 955 | ex->ex_phy[i].phy_state= PHY_DEVICE_DISCOVERED; |
| 956 | res = sas_ex_join_wide_port(dev, i); | ||
| 957 | if (!res) | ||
| 958 | SAS_DPRINTK("Attaching ex phy%d to wide port %016llx\n", | ||
| 959 | i, SAS_ADDR(ex->ex_phy[i].attached_sas_addr)); | ||
| 960 | |||
| 961 | } | ||
| 952 | } | 962 | } |
| 963 | res = 0; | ||
| 953 | } | 964 | } |
| 954 | 965 | ||
| 955 | return res; | 966 | return res; |
| @@ -1598,7 +1609,7 @@ static int sas_get_phy_attached_sas_addr(struct domain_device *dev, | |||
| 1598 | } | 1609 | } |
| 1599 | 1610 | ||
| 1600 | static int sas_find_bcast_phy(struct domain_device *dev, int *phy_id, | 1611 | static int sas_find_bcast_phy(struct domain_device *dev, int *phy_id, |
| 1601 | int from_phy) | 1612 | int from_phy, bool update) |
| 1602 | { | 1613 | { |
| 1603 | struct expander_device *ex = &dev->ex_dev; | 1614 | struct expander_device *ex = &dev->ex_dev; |
| 1604 | int res = 0; | 1615 | int res = 0; |
| @@ -1611,7 +1622,9 @@ static int sas_find_bcast_phy(struct domain_device *dev, int *phy_id, | |||
| 1611 | if (res) | 1622 | if (res) |
| 1612 | goto out; | 1623 | goto out; |
| 1613 | else if (phy_change_count != ex->ex_phy[i].phy_change_count) { | 1624 | else if (phy_change_count != ex->ex_phy[i].phy_change_count) { |
| 1614 | ex->ex_phy[i].phy_change_count = phy_change_count; | 1625 | if (update) |
| 1626 | ex->ex_phy[i].phy_change_count = | ||
| 1627 | phy_change_count; | ||
| 1615 | *phy_id = i; | 1628 | *phy_id = i; |
| 1616 | return 0; | 1629 | return 0; |
| 1617 | } | 1630 | } |
| @@ -1653,31 +1666,52 @@ out: | |||
| 1653 | kfree(rg_req); | 1666 | kfree(rg_req); |
| 1654 | return res; | 1667 | return res; |
| 1655 | } | 1668 | } |
| 1669 | /** | ||
| 1670 | * sas_find_bcast_dev - find the device issue BROADCAST(CHANGE). | ||
| 1671 | * @dev:domain device to be detect. | ||
| 1672 | * @src_dev: the device which originated BROADCAST(CHANGE). | ||
| 1673 | * | ||
| 1674 | * Add self-configuration expander suport. Suppose two expander cascading, | ||
| 1675 | * when the first level expander is self-configuring, hotplug the disks in | ||
| 1676 | * second level expander, BROADCAST(CHANGE) will not only be originated | ||
| 1677 | * in the second level expander, but also be originated in the first level | ||
| 1678 | * expander (see SAS protocol SAS 2r-14, 7.11 for detail), it is to say, | ||
| 1679 | * expander changed count in two level expanders will all increment at least | ||
| 1680 | * once, but the phy which chang count has changed is the source device which | ||
| 1681 | * we concerned. | ||
| 1682 | */ | ||
| 1656 | 1683 | ||
| 1657 | static int sas_find_bcast_dev(struct domain_device *dev, | 1684 | static int sas_find_bcast_dev(struct domain_device *dev, |
| 1658 | struct domain_device **src_dev) | 1685 | struct domain_device **src_dev) |
| 1659 | { | 1686 | { |
| 1660 | struct expander_device *ex = &dev->ex_dev; | 1687 | struct expander_device *ex = &dev->ex_dev; |
| 1661 | int ex_change_count = -1; | 1688 | int ex_change_count = -1; |
| 1689 | int phy_id = -1; | ||
| 1662 | int res; | 1690 | int res; |
| 1691 | struct domain_device *ch; | ||
| 1663 | 1692 | ||
| 1664 | res = sas_get_ex_change_count(dev, &ex_change_count); | 1693 | res = sas_get_ex_change_count(dev, &ex_change_count); |
| 1665 | if (res) | 1694 | if (res) |
| 1666 | goto out; | 1695 | goto out; |
| 1667 | if (ex_change_count != -1 && | 1696 | if (ex_change_count != -1 && ex_change_count != ex->ex_change_count) { |
| 1668 | ex_change_count != ex->ex_change_count) { | 1697 | /* Just detect if this expander phys phy change count changed, |
| 1669 | *src_dev = dev; | 1698 | * in order to determine if this expander originate BROADCAST, |
| 1670 | ex->ex_change_count = ex_change_count; | 1699 | * and do not update phy change count field in our structure. |
| 1671 | } else { | 1700 | */ |
| 1672 | struct domain_device *ch; | 1701 | res = sas_find_bcast_phy(dev, &phy_id, 0, false); |
| 1673 | 1702 | if (phy_id != -1) { | |
| 1674 | list_for_each_entry(ch, &ex->children, siblings) { | 1703 | *src_dev = dev; |
| 1675 | if (ch->dev_type == EDGE_DEV || | 1704 | ex->ex_change_count = ex_change_count; |
| 1676 | ch->dev_type == FANOUT_DEV) { | 1705 | SAS_DPRINTK("Expander phy change count has changed\n"); |
| 1677 | res = sas_find_bcast_dev(ch, src_dev); | 1706 | return res; |
| 1678 | if (src_dev) | 1707 | } else |
| 1679 | return res; | 1708 | SAS_DPRINTK("Expander phys DID NOT change\n"); |
| 1680 | } | 1709 | } |
| 1710 | list_for_each_entry(ch, &ex->children, siblings) { | ||
| 1711 | if (ch->dev_type == EDGE_DEV || ch->dev_type == FANOUT_DEV) { | ||
| 1712 | res = sas_find_bcast_dev(ch, src_dev); | ||
| 1713 | if (src_dev) | ||
| 1714 | return res; | ||
| 1681 | } | 1715 | } |
| 1682 | } | 1716 | } |
| 1683 | out: | 1717 | out: |
| @@ -1700,24 +1734,26 @@ static void sas_unregister_ex_tree(struct domain_device *dev) | |||
| 1700 | } | 1734 | } |
| 1701 | 1735 | ||
| 1702 | static void sas_unregister_devs_sas_addr(struct domain_device *parent, | 1736 | static void sas_unregister_devs_sas_addr(struct domain_device *parent, |
| 1703 | int phy_id) | 1737 | int phy_id, bool last) |
| 1704 | { | 1738 | { |
| 1705 | struct expander_device *ex_dev = &parent->ex_dev; | 1739 | struct expander_device *ex_dev = &parent->ex_dev; |
| 1706 | struct ex_phy *phy = &ex_dev->ex_phy[phy_id]; | 1740 | struct ex_phy *phy = &ex_dev->ex_phy[phy_id]; |
| 1707 | struct domain_device *child, *n; | 1741 | struct domain_device *child, *n; |
| 1708 | 1742 | if (last) { | |
| 1709 | list_for_each_entry_safe(child, n, &ex_dev->children, siblings) { | 1743 | list_for_each_entry_safe(child, n, |
| 1710 | if (SAS_ADDR(child->sas_addr) == | 1744 | &ex_dev->children, siblings) { |
| 1711 | SAS_ADDR(phy->attached_sas_addr)) { | 1745 | if (SAS_ADDR(child->sas_addr) == |
| 1712 | if (child->dev_type == EDGE_DEV || | 1746 | SAS_ADDR(phy->attached_sas_addr)) { |
| 1713 | child->dev_type == FANOUT_DEV) | 1747 | if (child->dev_type == EDGE_DEV || |
| 1714 | sas_unregister_ex_tree(child); | 1748 | child->dev_type == FANOUT_DEV) |
| 1715 | else | 1749 | sas_unregister_ex_tree(child); |
| 1716 | sas_unregister_dev(child); | 1750 | else |
| 1717 | break; | 1751 | sas_unregister_dev(child); |
| 1752 | break; | ||
| 1753 | } | ||
| 1718 | } | 1754 | } |
| 1755 | sas_disable_routing(parent, phy->attached_sas_addr); | ||
| 1719 | } | 1756 | } |
| 1720 | sas_disable_routing(parent, phy->attached_sas_addr); | ||
| 1721 | memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE); | 1757 | memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE); |
| 1722 | sas_port_delete_phy(phy->port, phy->phy); | 1758 | sas_port_delete_phy(phy->port, phy->phy); |
| 1723 | if (phy->port->num_phys == 0) | 1759 | if (phy->port->num_phys == 0) |
| @@ -1770,15 +1806,31 @@ static int sas_discover_new(struct domain_device *dev, int phy_id) | |||
| 1770 | { | 1806 | { |
| 1771 | struct ex_phy *ex_phy = &dev->ex_dev.ex_phy[phy_id]; | 1807 | struct ex_phy *ex_phy = &dev->ex_dev.ex_phy[phy_id]; |
| 1772 | struct domain_device *child; | 1808 | struct domain_device *child; |
| 1773 | int res; | 1809 | bool found = false; |
| 1810 | int res, i; | ||
| 1774 | 1811 | ||
| 1775 | SAS_DPRINTK("ex %016llx phy%d new device attached\n", | 1812 | SAS_DPRINTK("ex %016llx phy%d new device attached\n", |
| 1776 | SAS_ADDR(dev->sas_addr), phy_id); | 1813 | SAS_ADDR(dev->sas_addr), phy_id); |
| 1777 | res = sas_ex_phy_discover(dev, phy_id); | 1814 | res = sas_ex_phy_discover(dev, phy_id); |
| 1778 | if (res) | 1815 | if (res) |
| 1779 | goto out; | 1816 | goto out; |
| 1817 | /* to support the wide port inserted */ | ||
| 1818 | for (i = 0; i < dev->ex_dev.num_phys; i++) { | ||
| 1819 | struct ex_phy *ex_phy_temp = &dev->ex_dev.ex_phy[i]; | ||
| 1820 | if (i == phy_id) | ||
| 1821 | continue; | ||
| 1822 | if (SAS_ADDR(ex_phy_temp->attached_sas_addr) == | ||
| 1823 | SAS_ADDR(ex_phy->attached_sas_addr)) { | ||
| 1824 | found = true; | ||
| 1825 | break; | ||
| 1826 | } | ||
| 1827 | } | ||
| 1828 | if (found) { | ||
| 1829 | sas_ex_join_wide_port(dev, phy_id); | ||
| 1830 | return 0; | ||
| 1831 | } | ||
| 1780 | res = sas_ex_discover_devices(dev, phy_id); | 1832 | res = sas_ex_discover_devices(dev, phy_id); |
| 1781 | if (res) | 1833 | if (!res) |
| 1782 | goto out; | 1834 | goto out; |
| 1783 | list_for_each_entry(child, &dev->ex_dev.children, siblings) { | 1835 | list_for_each_entry(child, &dev->ex_dev.children, siblings) { |
| 1784 | if (SAS_ADDR(child->sas_addr) == | 1836 | if (SAS_ADDR(child->sas_addr) == |
| @@ -1793,7 +1845,7 @@ out: | |||
| 1793 | return res; | 1845 | return res; |
| 1794 | } | 1846 | } |
| 1795 | 1847 | ||
| 1796 | static int sas_rediscover_dev(struct domain_device *dev, int phy_id) | 1848 | static int sas_rediscover_dev(struct domain_device *dev, int phy_id, bool last) |
| 1797 | { | 1849 | { |
| 1798 | struct expander_device *ex = &dev->ex_dev; | 1850 | struct expander_device *ex = &dev->ex_dev; |
| 1799 | struct ex_phy *phy = &ex->ex_phy[phy_id]; | 1851 | struct ex_phy *phy = &ex->ex_phy[phy_id]; |
| @@ -1804,11 +1856,11 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id) | |||
| 1804 | switch (res) { | 1856 | switch (res) { |
| 1805 | case SMP_RESP_NO_PHY: | 1857 | case SMP_RESP_NO_PHY: |
| 1806 | phy->phy_state = PHY_NOT_PRESENT; | 1858 | phy->phy_state = PHY_NOT_PRESENT; |
| 1807 | sas_unregister_devs_sas_addr(dev, phy_id); | 1859 | sas_unregister_devs_sas_addr(dev, phy_id, last); |
| 1808 | goto out; break; | 1860 | goto out; break; |
| 1809 | case SMP_RESP_PHY_VACANT: | 1861 | case SMP_RESP_PHY_VACANT: |
| 1810 | phy->phy_state = PHY_VACANT; | 1862 | phy->phy_state = PHY_VACANT; |
| 1811 | sas_unregister_devs_sas_addr(dev, phy_id); | 1863 | sas_unregister_devs_sas_addr(dev, phy_id, last); |
| 1812 | goto out; break; | 1864 | goto out; break; |
| 1813 | case SMP_RESP_FUNC_ACC: | 1865 | case SMP_RESP_FUNC_ACC: |
| 1814 | break; | 1866 | break; |
| @@ -1816,7 +1868,7 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id) | |||
| 1816 | 1868 | ||
| 1817 | if (SAS_ADDR(attached_sas_addr) == 0) { | 1869 | if (SAS_ADDR(attached_sas_addr) == 0) { |
| 1818 | phy->phy_state = PHY_EMPTY; | 1870 | phy->phy_state = PHY_EMPTY; |
| 1819 | sas_unregister_devs_sas_addr(dev, phy_id); | 1871 | sas_unregister_devs_sas_addr(dev, phy_id, last); |
| 1820 | } else if (SAS_ADDR(attached_sas_addr) == | 1872 | } else if (SAS_ADDR(attached_sas_addr) == |
| 1821 | SAS_ADDR(phy->attached_sas_addr)) { | 1873 | SAS_ADDR(phy->attached_sas_addr)) { |
| 1822 | SAS_DPRINTK("ex %016llx phy 0x%x broadcast flutter\n", | 1874 | SAS_DPRINTK("ex %016llx phy 0x%x broadcast flutter\n", |
| @@ -1828,12 +1880,27 @@ out: | |||
| 1828 | return res; | 1880 | return res; |
| 1829 | } | 1881 | } |
| 1830 | 1882 | ||
| 1883 | /** | ||
| 1884 | * sas_rediscover - revalidate the domain. | ||
| 1885 | * @dev:domain device to be detect. | ||
| 1886 | * @phy_id: the phy id will be detected. | ||
| 1887 | * | ||
| 1888 | * NOTE: this process _must_ quit (return) as soon as any connection | ||
| 1889 | * errors are encountered. Connection recovery is done elsewhere. | ||
| 1890 | * Discover process only interrogates devices in order to discover the | ||
| 1891 | * domain.For plugging out, we un-register the device only when it is | ||
| 1892 | * the last phy in the port, for other phys in this port, we just delete it | ||
| 1893 | * from the port.For inserting, we do discovery when it is the | ||
| 1894 | * first phy,for other phys in this port, we add it to the port to | ||
| 1895 | * forming the wide-port. | ||
| 1896 | */ | ||
| 1831 | static int sas_rediscover(struct domain_device *dev, const int phy_id) | 1897 | static int sas_rediscover(struct domain_device *dev, const int phy_id) |
| 1832 | { | 1898 | { |
| 1833 | struct expander_device *ex = &dev->ex_dev; | 1899 | struct expander_device *ex = &dev->ex_dev; |
| 1834 | struct ex_phy *changed_phy = &ex->ex_phy[phy_id]; | 1900 | struct ex_phy *changed_phy = &ex->ex_phy[phy_id]; |
| 1835 | int res = 0; | 1901 | int res = 0; |
| 1836 | int i; | 1902 | int i; |
| 1903 | bool last = true; /* is this the last phy of the port */ | ||
| 1837 | 1904 | ||
| 1838 | SAS_DPRINTK("ex %016llx phy%d originated BROADCAST(CHANGE)\n", | 1905 | SAS_DPRINTK("ex %016llx phy%d originated BROADCAST(CHANGE)\n", |
| 1839 | SAS_ADDR(dev->sas_addr), phy_id); | 1906 | SAS_ADDR(dev->sas_addr), phy_id); |
| @@ -1848,13 +1915,13 @@ static int sas_rediscover(struct domain_device *dev, const int phy_id) | |||
| 1848 | SAS_ADDR(changed_phy->attached_sas_addr)) { | 1915 | SAS_ADDR(changed_phy->attached_sas_addr)) { |
| 1849 | SAS_DPRINTK("phy%d part of wide port with " | 1916 | SAS_DPRINTK("phy%d part of wide port with " |
| 1850 | "phy%d\n", phy_id, i); | 1917 | "phy%d\n", phy_id, i); |
| 1851 | goto out; | 1918 | last = false; |
| 1919 | break; | ||
| 1852 | } | 1920 | } |
| 1853 | } | 1921 | } |
| 1854 | res = sas_rediscover_dev(dev, phy_id); | 1922 | res = sas_rediscover_dev(dev, phy_id, last); |
| 1855 | } else | 1923 | } else |
| 1856 | res = sas_discover_new(dev, phy_id); | 1924 | res = sas_discover_new(dev, phy_id); |
| 1857 | out: | ||
| 1858 | return res; | 1925 | return res; |
| 1859 | } | 1926 | } |
| 1860 | 1927 | ||
| @@ -1881,7 +1948,7 @@ int sas_ex_revalidate_domain(struct domain_device *port_dev) | |||
| 1881 | 1948 | ||
| 1882 | do { | 1949 | do { |
| 1883 | phy_id = -1; | 1950 | phy_id = -1; |
| 1884 | res = sas_find_bcast_phy(dev, &phy_id, i); | 1951 | res = sas_find_bcast_phy(dev, &phy_id, i, true); |
| 1885 | if (phy_id == -1) | 1952 | if (phy_id == -1) |
| 1886 | break; | 1953 | break; |
| 1887 | res = sas_rediscover(dev, phy_id); | 1954 | res = sas_rediscover(dev, phy_id); |
diff --git a/drivers/scsi/libsas/sas_port.c b/drivers/scsi/libsas/sas_port.c index e6ac59c023f1..fe8b74c706d2 100644 --- a/drivers/scsi/libsas/sas_port.c +++ b/drivers/scsi/libsas/sas_port.c | |||
| @@ -56,7 +56,7 @@ static void sas_form_port(struct asd_sas_phy *phy) | |||
| 56 | } | 56 | } |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | /* find a port */ | 59 | /* see if the phy should be part of a wide port */ |
| 60 | spin_lock_irqsave(&sas_ha->phy_port_lock, flags); | 60 | spin_lock_irqsave(&sas_ha->phy_port_lock, flags); |
| 61 | for (i = 0; i < sas_ha->num_phys; i++) { | 61 | for (i = 0; i < sas_ha->num_phys; i++) { |
| 62 | port = sas_ha->sas_port[i]; | 62 | port = sas_ha->sas_port[i]; |
| @@ -69,12 +69,23 @@ static void sas_form_port(struct asd_sas_phy *phy) | |||
| 69 | SAS_DPRINTK("phy%d matched wide port%d\n", phy->id, | 69 | SAS_DPRINTK("phy%d matched wide port%d\n", phy->id, |
| 70 | port->id); | 70 | port->id); |
| 71 | break; | 71 | break; |
| 72 | } else if (*(u64 *) port->sas_addr == 0 && port->num_phys==0) { | ||
| 73 | memcpy(port->sas_addr, phy->sas_addr, SAS_ADDR_SIZE); | ||
| 74 | break; | ||
| 75 | } | 72 | } |
| 76 | spin_unlock(&port->phy_list_lock); | 73 | spin_unlock(&port->phy_list_lock); |
| 77 | } | 74 | } |
| 75 | /* The phy does not match any existing port, create a new one */ | ||
| 76 | if (i == sas_ha->num_phys) { | ||
| 77 | for (i = 0; i < sas_ha->num_phys; i++) { | ||
| 78 | port = sas_ha->sas_port[i]; | ||
| 79 | spin_lock(&port->phy_list_lock); | ||
| 80 | if (*(u64 *)port->sas_addr == 0 | ||
| 81 | && port->num_phys == 0) { | ||
| 82 | memcpy(port->sas_addr, phy->sas_addr, | ||
| 83 | SAS_ADDR_SIZE); | ||
| 84 | break; | ||
| 85 | } | ||
| 86 | spin_unlock(&port->phy_list_lock); | ||
| 87 | } | ||
| 88 | } | ||
| 78 | 89 | ||
| 79 | if (i >= sas_ha->num_phys) { | 90 | if (i >= sas_ha->num_phys) { |
| 80 | printk(KERN_NOTICE "%s: couldn't find a free port, bug?\n", | 91 | printk(KERN_NOTICE "%s: couldn't find a free port, bug?\n", |
diff --git a/drivers/scsi/qla4xxx/ql4_dbg.c b/drivers/scsi/qla4xxx/ql4_dbg.c index fcc184cd066d..cbceb0ebabf7 100644 --- a/drivers/scsi/qla4xxx/ql4_dbg.c +++ b/drivers/scsi/qla4xxx/ql4_dbg.c | |||
| @@ -15,19 +15,18 @@ void qla4xxx_dump_buffer(void *b, uint32_t size) | |||
| 15 | uint32_t cnt; | 15 | uint32_t cnt; |
| 16 | uint8_t *c = b; | 16 | uint8_t *c = b; |
| 17 | 17 | ||
| 18 | printk(" 0 1 2 3 4 5 6 7 8 9 Ah Bh Ch Dh Eh " | 18 | printk(" 0 1 2 3 4 5 6 7 8 9 Ah Bh Ch Dh Eh " |
| 19 | "Fh\n"); | 19 | "Fh\n"); |
| 20 | printk("------------------------------------------------------------" | 20 | printk("------------------------------------------------------------" |
| 21 | "--\n"); | 21 | "--\n"); |
| 22 | for (cnt = 0; cnt < size; cnt++, c++) { | 22 | for (cnt = 0; cnt < size; c++) { |
| 23 | printk(KERN_DEBUG "%02x", *c); | 23 | printk(KERN_INFO "%02x", *c); |
| 24 | if (!(cnt % 16)) | 24 | if (!(++cnt % 16)) |
| 25 | printk(KERN_DEBUG "\n"); | 25 | printk(KERN_INFO "\n"); |
| 26 | 26 | ||
| 27 | else | 27 | else |
| 28 | printk(KERN_DEBUG " "); | 28 | printk(KERN_INFO " "); |
| 29 | } | 29 | } |
| 30 | if (cnt % 16) | 30 | printk(KERN_INFO "\n"); |
| 31 | printk(KERN_DEBUG "\n"); | ||
| 32 | } | 31 | } |
| 33 | 32 | ||
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index b586f27c3bd4..81b5f29254e2 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h | |||
| @@ -100,7 +100,6 @@ | |||
| 100 | #define MAX_SRBS MAX_CMDS_TO_RISC | 100 | #define MAX_SRBS MAX_CMDS_TO_RISC |
| 101 | #define MBOX_AEN_REG_COUNT 5 | 101 | #define MBOX_AEN_REG_COUNT 5 |
| 102 | #define MAX_INIT_RETRIES 5 | 102 | #define MAX_INIT_RETRIES 5 |
| 103 | #define IOCB_HIWAT_CUSHION 16 | ||
| 104 | 103 | ||
| 105 | /* | 104 | /* |
| 106 | * Buffer sizes | 105 | * Buffer sizes |
| @@ -184,6 +183,11 @@ struct srb { | |||
| 184 | uint16_t cc_stat; | 183 | uint16_t cc_stat; |
| 185 | u_long r_start; /* Time we recieve a cmd from OS */ | 184 | u_long r_start; /* Time we recieve a cmd from OS */ |
| 186 | u_long u_start; /* Time when we handed the cmd to F/W */ | 185 | u_long u_start; /* Time when we handed the cmd to F/W */ |
| 186 | |||
| 187 | /* Used for extended sense / status continuation */ | ||
| 188 | uint8_t *req_sense_ptr; | ||
| 189 | uint16_t req_sense_len; | ||
| 190 | uint16_t reserved2; | ||
| 187 | }; | 191 | }; |
| 188 | 192 | ||
| 189 | /* | 193 | /* |
| @@ -302,7 +306,6 @@ struct scsi_qla_host { | |||
| 302 | uint32_t tot_ddbs; | 306 | uint32_t tot_ddbs; |
| 303 | 307 | ||
| 304 | uint16_t iocb_cnt; | 308 | uint16_t iocb_cnt; |
| 305 | uint16_t iocb_hiwat; | ||
| 306 | 309 | ||
| 307 | /* SRB cache. */ | 310 | /* SRB cache. */ |
| 308 | #define SRB_MIN_REQ 128 | 311 | #define SRB_MIN_REQ 128 |
| @@ -436,6 +439,8 @@ struct scsi_qla_host { | |||
| 436 | /* Map ddb_list entry by FW ddb index */ | 439 | /* Map ddb_list entry by FW ddb index */ |
| 437 | struct ddb_entry *fw_ddb_index_map[MAX_DDB_ENTRIES]; | 440 | struct ddb_entry *fw_ddb_index_map[MAX_DDB_ENTRIES]; |
| 438 | 441 | ||
| 442 | /* Saved srb for status continuation entry processing */ | ||
| 443 | struct srb *status_srb; | ||
| 439 | }; | 444 | }; |
| 440 | 445 | ||
| 441 | static inline int is_qla4010(struct scsi_qla_host *ha) | 446 | static inline int is_qla4010(struct scsi_qla_host *ha) |
diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h index 1b667a70cffa..9cd7a608df38 100644 --- a/drivers/scsi/qla4xxx/ql4_fw.h +++ b/drivers/scsi/qla4xxx/ql4_fw.h | |||
| @@ -572,6 +572,7 @@ struct conn_event_log_entry { | |||
| 572 | *************************************************************************/ | 572 | *************************************************************************/ |
| 573 | #define IOCB_MAX_CDB_LEN 16 /* Bytes in a CBD */ | 573 | #define IOCB_MAX_CDB_LEN 16 /* Bytes in a CBD */ |
| 574 | #define IOCB_MAX_SENSEDATA_LEN 32 /* Bytes of sense data */ | 574 | #define IOCB_MAX_SENSEDATA_LEN 32 /* Bytes of sense data */ |
| 575 | #define IOCB_MAX_EXT_SENSEDATA_LEN 60 /* Bytes of extended sense data */ | ||
| 575 | 576 | ||
| 576 | /* IOCB header structure */ | 577 | /* IOCB header structure */ |
| 577 | struct qla4_header { | 578 | struct qla4_header { |
| @@ -733,6 +734,12 @@ struct status_entry { | |||
| 733 | 734 | ||
| 734 | }; | 735 | }; |
| 735 | 736 | ||
| 737 | /* Status Continuation entry */ | ||
| 738 | struct status_cont_entry { | ||
| 739 | struct qla4_header hdr; /* 00-03 */ | ||
| 740 | uint8_t ext_sense_data[IOCB_MAX_EXT_SENSEDATA_LEN]; /* 04-63 */ | ||
| 741 | }; | ||
| 742 | |||
| 736 | struct passthru0 { | 743 | struct passthru0 { |
| 737 | struct qla4_header hdr; /* 00-03 */ | 744 | struct qla4_header hdr; /* 00-03 */ |
| 738 | uint32_t handle; /* 04-07 */ | 745 | uint32_t handle; /* 04-07 */ |
diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c index 912a67494adf..e0c32159749c 100644 --- a/drivers/scsi/qla4xxx/ql4_iocb.c +++ b/drivers/scsi/qla4xxx/ql4_iocb.c | |||
| @@ -10,9 +10,42 @@ | |||
| 10 | #include "ql4_dbg.h" | 10 | #include "ql4_dbg.h" |
| 11 | #include "ql4_inline.h" | 11 | #include "ql4_inline.h" |
| 12 | 12 | ||
| 13 | |||
| 14 | #include <scsi/scsi_tcq.h> | 13 | #include <scsi/scsi_tcq.h> |
| 15 | 14 | ||
| 15 | static int | ||
| 16 | qla4xxx_space_in_req_ring(struct scsi_qla_host *ha, uint16_t req_cnt) | ||
| 17 | { | ||
| 18 | uint16_t cnt; | ||
| 19 | |||
| 20 | /* Calculate number of free request entries. */ | ||
| 21 | if ((req_cnt + 2) >= ha->req_q_count) { | ||
| 22 | cnt = (uint16_t) le32_to_cpu(ha->shadow_regs->req_q_out); | ||
| 23 | if (ha->request_in < cnt) | ||
| 24 | ha->req_q_count = cnt - ha->request_in; | ||
| 25 | else | ||
| 26 | ha->req_q_count = REQUEST_QUEUE_DEPTH - | ||
| 27 | (ha->request_in - cnt); | ||
| 28 | } | ||
| 29 | |||
| 30 | /* Check if room for request in request ring. */ | ||
| 31 | if ((req_cnt + 2) < ha->req_q_count) | ||
| 32 | return 1; | ||
| 33 | else | ||
| 34 | return 0; | ||
| 35 | } | ||
| 36 | |||
| 37 | static void qla4xxx_advance_req_ring_ptr(struct scsi_qla_host *ha) | ||
| 38 | { | ||
| 39 | /* Advance request queue pointer */ | ||
| 40 | if (ha->request_in == (REQUEST_QUEUE_DEPTH - 1)) { | ||
| 41 | ha->request_in = 0; | ||
| 42 | ha->request_ptr = ha->request_ring; | ||
| 43 | } else { | ||
| 44 | ha->request_in++; | ||
| 45 | ha->request_ptr++; | ||
| 46 | } | ||
| 47 | } | ||
| 48 | |||
| 16 | /** | 49 | /** |
| 17 | * qla4xxx_get_req_pkt - returns a valid entry in request queue. | 50 | * qla4xxx_get_req_pkt - returns a valid entry in request queue. |
| 18 | * @ha: Pointer to host adapter structure. | 51 | * @ha: Pointer to host adapter structure. |
| @@ -26,35 +59,18 @@ | |||
| 26 | static int qla4xxx_get_req_pkt(struct scsi_qla_host *ha, | 59 | static int qla4xxx_get_req_pkt(struct scsi_qla_host *ha, |
| 27 | struct queue_entry **queue_entry) | 60 | struct queue_entry **queue_entry) |
| 28 | { | 61 | { |
| 29 | uint16_t request_in; | 62 | uint16_t req_cnt = 1; |
| 30 | uint8_t status = QLA_SUCCESS; | ||
| 31 | |||
| 32 | *queue_entry = ha->request_ptr; | ||
| 33 | 63 | ||
| 34 | /* get the latest request_in and request_out index */ | 64 | if (qla4xxx_space_in_req_ring(ha, req_cnt)) { |
| 35 | request_in = ha->request_in; | 65 | *queue_entry = ha->request_ptr; |
| 36 | ha->request_out = (uint16_t) le32_to_cpu(ha->shadow_regs->req_q_out); | ||
| 37 | |||
| 38 | /* Advance request queue pointer and check for queue full */ | ||
| 39 | if (request_in == (REQUEST_QUEUE_DEPTH - 1)) { | ||
| 40 | request_in = 0; | ||
| 41 | ha->request_ptr = ha->request_ring; | ||
| 42 | } else { | ||
| 43 | request_in++; | ||
| 44 | ha->request_ptr++; | ||
| 45 | } | ||
| 46 | |||
| 47 | /* request queue is full, try again later */ | ||
| 48 | if ((ha->iocb_cnt + 1) >= ha->iocb_hiwat) { | ||
| 49 | /* restore request pointer */ | ||
| 50 | ha->request_ptr = *queue_entry; | ||
| 51 | status = QLA_ERROR; | ||
| 52 | } else { | ||
| 53 | ha->request_in = request_in; | ||
| 54 | memset(*queue_entry, 0, sizeof(**queue_entry)); | 66 | memset(*queue_entry, 0, sizeof(**queue_entry)); |
| 67 | |||
| 68 | qla4xxx_advance_req_ring_ptr(ha); | ||
| 69 | ha->req_q_count -= req_cnt; | ||
| 70 | return QLA_SUCCESS; | ||
| 55 | } | 71 | } |
| 56 | 72 | ||
| 57 | return status; | 73 | return QLA_ERROR; |
| 58 | } | 74 | } |
| 59 | 75 | ||
| 60 | /** | 76 | /** |
| @@ -100,21 +116,14 @@ exit_send_marker: | |||
| 100 | return status; | 116 | return status; |
| 101 | } | 117 | } |
| 102 | 118 | ||
| 103 | static struct continuation_t1_entry* qla4xxx_alloc_cont_entry( | 119 | static struct continuation_t1_entry * |
| 104 | struct scsi_qla_host *ha) | 120 | qla4xxx_alloc_cont_entry(struct scsi_qla_host *ha) |
| 105 | { | 121 | { |
| 106 | struct continuation_t1_entry *cont_entry; | 122 | struct continuation_t1_entry *cont_entry; |
| 107 | 123 | ||
| 108 | cont_entry = (struct continuation_t1_entry *)ha->request_ptr; | 124 | cont_entry = (struct continuation_t1_entry *)ha->request_ptr; |
| 109 | 125 | ||
| 110 | /* Advance request queue pointer */ | 126 | qla4xxx_advance_req_ring_ptr(ha); |
| 111 | if (ha->request_in == (REQUEST_QUEUE_DEPTH - 1)) { | ||
| 112 | ha->request_in = 0; | ||
| 113 | ha->request_ptr = ha->request_ring; | ||
| 114 | } else { | ||
| 115 | ha->request_in++; | ||
| 116 | ha->request_ptr++; | ||
| 117 | } | ||
| 118 | 127 | ||
| 119 | /* Load packet defaults */ | 128 | /* Load packet defaults */ |
| 120 | cont_entry->hdr.entryType = ET_CONTINUE; | 129 | cont_entry->hdr.entryType = ET_CONTINUE; |
| @@ -197,13 +206,10 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb) | |||
| 197 | struct scsi_cmnd *cmd = srb->cmd; | 206 | struct scsi_cmnd *cmd = srb->cmd; |
| 198 | struct ddb_entry *ddb_entry; | 207 | struct ddb_entry *ddb_entry; |
| 199 | struct command_t3_entry *cmd_entry; | 208 | struct command_t3_entry *cmd_entry; |
| 200 | |||
| 201 | int nseg; | 209 | int nseg; |
| 202 | uint16_t tot_dsds; | 210 | uint16_t tot_dsds; |
| 203 | uint16_t req_cnt; | 211 | uint16_t req_cnt; |
| 204 | |||
| 205 | unsigned long flags; | 212 | unsigned long flags; |
| 206 | uint16_t cnt; | ||
| 207 | uint32_t index; | 213 | uint32_t index; |
| 208 | char tag[2]; | 214 | char tag[2]; |
| 209 | 215 | ||
| @@ -217,6 +223,19 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb) | |||
| 217 | 223 | ||
| 218 | index = (uint32_t)cmd->request->tag; | 224 | index = (uint32_t)cmd->request->tag; |
| 219 | 225 | ||
| 226 | /* | ||
| 227 | * Check to see if adapter is online before placing request on | ||
| 228 | * request queue. If a reset occurs and a request is in the queue, | ||
| 229 | * the firmware will still attempt to process the request, retrieving | ||
| 230 | * garbage for pointers. | ||
| 231 | */ | ||
| 232 | if (!test_bit(AF_ONLINE, &ha->flags)) { | ||
| 233 | DEBUG2(printk("scsi%ld: %s: Adapter OFFLINE! " | ||
| 234 | "Do not issue command.\n", | ||
| 235 | ha->host_no, __func__)); | ||
| 236 | goto queuing_error; | ||
| 237 | } | ||
| 238 | |||
| 220 | /* Calculate the number of request entries needed. */ | 239 | /* Calculate the number of request entries needed. */ |
| 221 | nseg = scsi_dma_map(cmd); | 240 | nseg = scsi_dma_map(cmd); |
| 222 | if (nseg < 0) | 241 | if (nseg < 0) |
| @@ -224,17 +243,7 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb) | |||
| 224 | tot_dsds = nseg; | 243 | tot_dsds = nseg; |
| 225 | 244 | ||
| 226 | req_cnt = qla4xxx_calc_request_entries(tot_dsds); | 245 | req_cnt = qla4xxx_calc_request_entries(tot_dsds); |
| 227 | 246 | if (!qla4xxx_space_in_req_ring(ha, req_cnt)) | |
| 228 | if (ha->req_q_count < (req_cnt + 2)) { | ||
| 229 | cnt = (uint16_t) le32_to_cpu(ha->shadow_regs->req_q_out); | ||
| 230 | if (ha->request_in < cnt) | ||
| 231 | ha->req_q_count = cnt - ha->request_in; | ||
| 232 | else | ||
| 233 | ha->req_q_count = REQUEST_QUEUE_DEPTH - | ||
| 234 | (ha->request_in - cnt); | ||
| 235 | } | ||
| 236 | |||
| 237 | if (ha->req_q_count < (req_cnt + 2)) | ||
| 238 | goto queuing_error; | 247 | goto queuing_error; |
| 239 | 248 | ||
| 240 | /* total iocbs active */ | 249 | /* total iocbs active */ |
| @@ -286,32 +295,10 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb) | |||
| 286 | break; | 295 | break; |
| 287 | } | 296 | } |
| 288 | 297 | ||
| 289 | 298 | qla4xxx_advance_req_ring_ptr(ha); | |
| 290 | /* Advance request queue pointer */ | ||
| 291 | ha->request_in++; | ||
| 292 | if (ha->request_in == REQUEST_QUEUE_DEPTH) { | ||
| 293 | ha->request_in = 0; | ||
| 294 | ha->request_ptr = ha->request_ring; | ||
| 295 | } else | ||
| 296 | ha->request_ptr++; | ||
| 297 | |||
| 298 | |||
| 299 | qla4xxx_build_scsi_iocbs(srb, cmd_entry, tot_dsds); | 299 | qla4xxx_build_scsi_iocbs(srb, cmd_entry, tot_dsds); |
| 300 | wmb(); | 300 | wmb(); |
| 301 | 301 | ||
| 302 | /* | ||
| 303 | * Check to see if adapter is online before placing request on | ||
| 304 | * request queue. If a reset occurs and a request is in the queue, | ||
| 305 | * the firmware will still attempt to process the request, retrieving | ||
| 306 | * garbage for pointers. | ||
| 307 | */ | ||
| 308 | if (!test_bit(AF_ONLINE, &ha->flags)) { | ||
| 309 | DEBUG2(printk("scsi%ld: %s: Adapter OFFLINE! " | ||
| 310 | "Do not issue command.\n", | ||
| 311 | ha->host_no, __func__)); | ||
| 312 | goto queuing_error; | ||
| 313 | } | ||
| 314 | |||
| 315 | srb->cmd->host_scribble = (unsigned char *)srb; | 302 | srb->cmd->host_scribble = (unsigned char *)srb; |
| 316 | 303 | ||
| 317 | /* update counters */ | 304 | /* update counters */ |
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index 799120fcb9be..8025ee16588e 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c | |||
| @@ -11,6 +11,98 @@ | |||
| 11 | #include "ql4_inline.h" | 11 | #include "ql4_inline.h" |
| 12 | 12 | ||
| 13 | /** | 13 | /** |
| 14 | * qla4xxx_copy_sense - copy sense data into cmd sense buffer | ||
| 15 | * @ha: Pointer to host adapter structure. | ||
| 16 | * @sts_entry: Pointer to status entry structure. | ||
| 17 | * @srb: Pointer to srb structure. | ||
| 18 | **/ | ||
| 19 | static void qla4xxx_copy_sense(struct scsi_qla_host *ha, | ||
| 20 | struct status_entry *sts_entry, | ||
| 21 | struct srb *srb) | ||
| 22 | { | ||
| 23 | struct scsi_cmnd *cmd = srb->cmd; | ||
| 24 | uint16_t sense_len; | ||
| 25 | |||
| 26 | memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); | ||
| 27 | sense_len = le16_to_cpu(sts_entry->senseDataByteCnt); | ||
| 28 | if (sense_len == 0) | ||
| 29 | return; | ||
| 30 | |||
| 31 | /* Save total available sense length, | ||
| 32 | * not to exceed cmd's sense buffer size */ | ||
| 33 | sense_len = min_t(uint16_t, sense_len, SCSI_SENSE_BUFFERSIZE); | ||
| 34 | srb->req_sense_ptr = cmd->sense_buffer; | ||
| 35 | srb->req_sense_len = sense_len; | ||
| 36 | |||
| 37 | /* Copy sense from sts_entry pkt */ | ||
| 38 | sense_len = min_t(uint16_t, sense_len, IOCB_MAX_SENSEDATA_LEN); | ||
| 39 | memcpy(cmd->sense_buffer, sts_entry->senseData, sense_len); | ||
| 40 | |||
| 41 | DEBUG2(printk(KERN_INFO "scsi%ld:%d:%d:%d: %s: sense key = %x, " | ||
| 42 | "ASL= %02x, ASC/ASCQ = %02x/%02x\n", ha->host_no, | ||
| 43 | cmd->device->channel, cmd->device->id, | ||
| 44 | cmd->device->lun, __func__, | ||
| 45 | sts_entry->senseData[2] & 0x0f, | ||
| 46 | sts_entry->senseData[7], | ||
| 47 | sts_entry->senseData[12], | ||
| 48 | sts_entry->senseData[13])); | ||
| 49 | |||
| 50 | DEBUG5(qla4xxx_dump_buffer(cmd->sense_buffer, sense_len)); | ||
| 51 | srb->flags |= SRB_GOT_SENSE; | ||
| 52 | |||
| 53 | /* Update srb, in case a sts_cont pkt follows */ | ||
| 54 | srb->req_sense_ptr += sense_len; | ||
| 55 | srb->req_sense_len -= sense_len; | ||
| 56 | if (srb->req_sense_len != 0) | ||
| 57 | ha->status_srb = srb; | ||
| 58 | else | ||
| 59 | ha->status_srb = NULL; | ||
| 60 | } | ||
| 61 | |||
| 62 | /** | ||
| 63 | * qla4xxx_status_cont_entry - Process a Status Continuations entry. | ||
| 64 | * @ha: SCSI driver HA context | ||
| 65 | * @sts_cont: Entry pointer | ||
| 66 | * | ||
| 67 | * Extended sense data. | ||
| 68 | */ | ||
| 69 | static void | ||
| 70 | qla4xxx_status_cont_entry(struct scsi_qla_host *ha, | ||
| 71 | struct status_cont_entry *sts_cont) | ||
| 72 | { | ||
| 73 | struct srb *srb = ha->status_srb; | ||
| 74 | struct scsi_cmnd *cmd; | ||
| 75 | uint8_t sense_len; | ||
| 76 | |||
| 77 | if (srb == NULL) | ||
| 78 | return; | ||
| 79 | |||
| 80 | cmd = srb->cmd; | ||
| 81 | if (cmd == NULL) { | ||
| 82 | DEBUG2(printk(KERN_INFO "scsi%ld: %s: Cmd already returned " | ||
| 83 | "back to OS srb=%p srb->state:%d\n", ha->host_no, | ||
| 84 | __func__, srb, srb->state)); | ||
| 85 | ha->status_srb = NULL; | ||
| 86 | return; | ||
| 87 | } | ||
| 88 | |||
| 89 | /* Copy sense data. */ | ||
| 90 | sense_len = min_t(uint16_t, srb->req_sense_len, | ||
| 91 | IOCB_MAX_EXT_SENSEDATA_LEN); | ||
| 92 | memcpy(srb->req_sense_ptr, sts_cont->ext_sense_data, sense_len); | ||
| 93 | DEBUG5(qla4xxx_dump_buffer(srb->req_sense_ptr, sense_len)); | ||
| 94 | |||
| 95 | srb->req_sense_ptr += sense_len; | ||
| 96 | srb->req_sense_len -= sense_len; | ||
| 97 | |||
| 98 | /* Place command on done queue. */ | ||
| 99 | if (srb->req_sense_len == 0) { | ||
| 100 | qla4xxx_srb_compl(ha, srb); | ||
| 101 | ha->status_srb = NULL; | ||
| 102 | } | ||
| 103 | } | ||
| 104 | |||
| 105 | /** | ||
| 14 | * qla4xxx_status_entry - processes status IOCBs | 106 | * qla4xxx_status_entry - processes status IOCBs |
| 15 | * @ha: Pointer to host adapter structure. | 107 | * @ha: Pointer to host adapter structure. |
| 16 | * @sts_entry: Pointer to status entry structure. | 108 | * @sts_entry: Pointer to status entry structure. |
| @@ -23,7 +115,6 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, | |||
| 23 | struct srb *srb; | 115 | struct srb *srb; |
| 24 | struct ddb_entry *ddb_entry; | 116 | struct ddb_entry *ddb_entry; |
| 25 | uint32_t residual; | 117 | uint32_t residual; |
| 26 | uint16_t sensebytecnt; | ||
| 27 | 118 | ||
| 28 | srb = qla4xxx_del_from_active_array(ha, le32_to_cpu(sts_entry->handle)); | 119 | srb = qla4xxx_del_from_active_array(ha, le32_to_cpu(sts_entry->handle)); |
| 29 | if (!srb) { | 120 | if (!srb) { |
| @@ -92,24 +183,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, | |||
| 92 | break; | 183 | break; |
| 93 | 184 | ||
| 94 | /* Copy Sense Data into sense buffer. */ | 185 | /* Copy Sense Data into sense buffer. */ |
| 95 | memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); | 186 | qla4xxx_copy_sense(ha, sts_entry, srb); |
| 96 | |||
| 97 | sensebytecnt = le16_to_cpu(sts_entry->senseDataByteCnt); | ||
| 98 | if (sensebytecnt == 0) | ||
| 99 | break; | ||
| 100 | |||
| 101 | memcpy(cmd->sense_buffer, sts_entry->senseData, | ||
| 102 | min_t(uint16_t, sensebytecnt, SCSI_SENSE_BUFFERSIZE)); | ||
| 103 | |||
| 104 | DEBUG2(printk("scsi%ld:%d:%d:%d: %s: sense key = %x, " | ||
| 105 | "ASC/ASCQ = %02x/%02x\n", ha->host_no, | ||
| 106 | cmd->device->channel, cmd->device->id, | ||
| 107 | cmd->device->lun, __func__, | ||
| 108 | sts_entry->senseData[2] & 0x0f, | ||
| 109 | sts_entry->senseData[12], | ||
| 110 | sts_entry->senseData[13])); | ||
| 111 | |||
| 112 | srb->flags |= SRB_GOT_SENSE; | ||
| 113 | break; | 187 | break; |
| 114 | 188 | ||
| 115 | case SCS_INCOMPLETE: | 189 | case SCS_INCOMPLETE: |
| @@ -176,23 +250,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, | |||
| 176 | break; | 250 | break; |
| 177 | 251 | ||
| 178 | /* Copy Sense Data into sense buffer. */ | 252 | /* Copy Sense Data into sense buffer. */ |
| 179 | memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); | 253 | qla4xxx_copy_sense(ha, sts_entry, srb); |
| 180 | |||
| 181 | sensebytecnt = | ||
| 182 | le16_to_cpu(sts_entry->senseDataByteCnt); | ||
| 183 | if (sensebytecnt == 0) | ||
| 184 | break; | ||
| 185 | |||
| 186 | memcpy(cmd->sense_buffer, sts_entry->senseData, | ||
| 187 | min_t(uint16_t, sensebytecnt, SCSI_SENSE_BUFFERSIZE)); | ||
| 188 | |||
| 189 | DEBUG2(printk("scsi%ld:%d:%d:%d: %s: sense key = %x, " | ||
| 190 | "ASC/ASCQ = %02x/%02x\n", ha->host_no, | ||
| 191 | cmd->device->channel, cmd->device->id, | ||
| 192 | cmd->device->lun, __func__, | ||
| 193 | sts_entry->senseData[2] & 0x0f, | ||
| 194 | sts_entry->senseData[12], | ||
| 195 | sts_entry->senseData[13])); | ||
| 196 | } else { | 254 | } else { |
| 197 | /* | 255 | /* |
| 198 | * If RISC reports underrun and target does not | 256 | * If RISC reports underrun and target does not |
| @@ -268,9 +326,10 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, | |||
| 268 | 326 | ||
| 269 | status_entry_exit: | 327 | status_entry_exit: |
| 270 | 328 | ||
| 271 | /* complete the request */ | 329 | /* complete the request, if not waiting for status_continuation pkt */ |
| 272 | srb->cc_stat = sts_entry->completionStatus; | 330 | srb->cc_stat = sts_entry->completionStatus; |
| 273 | qla4xxx_srb_compl(ha, srb); | 331 | if (ha->status_srb == NULL) |
| 332 | qla4xxx_srb_compl(ha, srb); | ||
| 274 | } | 333 | } |
| 275 | 334 | ||
| 276 | /** | 335 | /** |
| @@ -305,10 +364,7 @@ static void qla4xxx_process_response_queue(struct scsi_qla_host * ha) | |||
| 305 | /* process entry */ | 364 | /* process entry */ |
| 306 | switch (sts_entry->hdr.entryType) { | 365 | switch (sts_entry->hdr.entryType) { |
| 307 | case ET_STATUS: | 366 | case ET_STATUS: |
| 308 | /* | 367 | /* Common status */ |
| 309 | * Common status - Single completion posted in single | ||
| 310 | * IOSB. | ||
| 311 | */ | ||
| 312 | qla4xxx_status_entry(ha, sts_entry); | 368 | qla4xxx_status_entry(ha, sts_entry); |
| 313 | break; | 369 | break; |
| 314 | 370 | ||
| @@ -316,9 +372,8 @@ static void qla4xxx_process_response_queue(struct scsi_qla_host * ha) | |||
| 316 | break; | 372 | break; |
| 317 | 373 | ||
| 318 | case ET_STATUS_CONTINUATION: | 374 | case ET_STATUS_CONTINUATION: |
| 319 | /* Just throw away the status continuation entries */ | 375 | qla4xxx_status_cont_entry(ha, |
| 320 | DEBUG2(printk("scsi%ld: %s: Status Continuation entry " | 376 | (struct status_cont_entry *) sts_entry); |
| 321 | "- ignoring\n", ha->host_no, __func__)); | ||
| 322 | break; | 377 | break; |
| 323 | 378 | ||
| 324 | case ET_COMMAND: | 379 | case ET_COMMAND: |
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index 051b0f5e8c8e..09d6d4b76f39 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c | |||
| @@ -385,16 +385,6 @@ int qla4xxx_get_firmware_status(struct scsi_qla_host * ha) | |||
| 385 | mbox_sts[0])); | 385 | mbox_sts[0])); |
| 386 | return QLA_ERROR; | 386 | return QLA_ERROR; |
| 387 | } | 387 | } |
| 388 | |||
| 389 | /* High-water mark of IOCBs */ | ||
| 390 | ha->iocb_hiwat = mbox_sts[2]; | ||
| 391 | if (ha->iocb_hiwat > IOCB_HIWAT_CUSHION) | ||
| 392 | ha->iocb_hiwat -= IOCB_HIWAT_CUSHION; | ||
| 393 | else | ||
| 394 | dev_info(&ha->pdev->dev, "WARNING!!! You have less than %d " | ||
| 395 | "firmware IOCBs available (%d).\n", | ||
| 396 | IOCB_HIWAT_CUSHION, ha->iocb_hiwat); | ||
| 397 | |||
| 398 | return QLA_SUCCESS; | 388 | return QLA_SUCCESS; |
| 399 | } | 389 | } |
| 400 | 390 | ||
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index ec9da6ce8489..40e3cafb3a9c 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c | |||
| @@ -66,6 +66,7 @@ static int qla4xxx_sess_get_param(struct iscsi_cls_session *sess, | |||
| 66 | static int qla4xxx_host_get_param(struct Scsi_Host *shost, | 66 | static int qla4xxx_host_get_param(struct Scsi_Host *shost, |
| 67 | enum iscsi_host_param param, char *buf); | 67 | enum iscsi_host_param param, char *buf); |
| 68 | static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session); | 68 | static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session); |
| 69 | static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc); | ||
| 69 | 70 | ||
| 70 | /* | 71 | /* |
| 71 | * SCSI host template entry points | 72 | * SCSI host template entry points |
| @@ -89,6 +90,7 @@ static struct scsi_host_template qla4xxx_driver_template = { | |||
| 89 | .eh_device_reset_handler = qla4xxx_eh_device_reset, | 90 | .eh_device_reset_handler = qla4xxx_eh_device_reset, |
| 90 | .eh_target_reset_handler = qla4xxx_eh_target_reset, | 91 | .eh_target_reset_handler = qla4xxx_eh_target_reset, |
| 91 | .eh_host_reset_handler = qla4xxx_eh_host_reset, | 92 | .eh_host_reset_handler = qla4xxx_eh_host_reset, |
| 93 | .eh_timed_out = qla4xxx_eh_cmd_timed_out, | ||
| 92 | 94 | ||
| 93 | .slave_configure = qla4xxx_slave_configure, | 95 | .slave_configure = qla4xxx_slave_configure, |
| 94 | .slave_alloc = qla4xxx_slave_alloc, | 96 | .slave_alloc = qla4xxx_slave_alloc, |
| @@ -124,6 +126,21 @@ static struct iscsi_transport qla4xxx_iscsi_transport = { | |||
| 124 | 126 | ||
| 125 | static struct scsi_transport_template *qla4xxx_scsi_transport; | 127 | static struct scsi_transport_template *qla4xxx_scsi_transport; |
| 126 | 128 | ||
| 129 | static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc) | ||
| 130 | { | ||
| 131 | struct iscsi_cls_session *session; | ||
| 132 | struct ddb_entry *ddb_entry; | ||
| 133 | |||
| 134 | session = starget_to_session(scsi_target(sc->device)); | ||
| 135 | ddb_entry = session->dd_data; | ||
| 136 | |||
| 137 | /* if we are not logged in then the LLD is going to clean up the cmd */ | ||
| 138 | if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) | ||
| 139 | return BLK_EH_RESET_TIMER; | ||
| 140 | else | ||
| 141 | return BLK_EH_NOT_HANDLED; | ||
| 142 | } | ||
| 143 | |||
| 127 | static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session) | 144 | static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session) |
| 128 | { | 145 | { |
| 129 | struct ddb_entry *ddb_entry = session->dd_data; | 146 | struct ddb_entry *ddb_entry = session->dd_data; |
| @@ -904,18 +921,17 @@ static int qla4xxx_recover_adapter(struct scsi_qla_host *ha, | |||
| 904 | /* Flush any pending ddb changed AENs */ | 921 | /* Flush any pending ddb changed AENs */ |
| 905 | qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); | 922 | qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); |
| 906 | 923 | ||
| 924 | qla4xxx_flush_active_srbs(ha); | ||
| 925 | |||
| 907 | /* Reset the firmware. If successful, function | 926 | /* Reset the firmware. If successful, function |
| 908 | * returns with ISP interrupts enabled. | 927 | * returns with ISP interrupts enabled. |
| 909 | */ | 928 | */ |
| 910 | if (status == QLA_SUCCESS) { | 929 | DEBUG2(printk("scsi%ld: %s - Performing soft reset..\n", |
| 911 | DEBUG2(printk("scsi%ld: %s - Performing soft reset..\n", | 930 | ha->host_no, __func__)); |
| 912 | ha->host_no, __func__)); | 931 | if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) |
| 913 | qla4xxx_flush_active_srbs(ha); | 932 | status = qla4xxx_soft_reset(ha); |
| 914 | if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) | 933 | else |
| 915 | status = qla4xxx_soft_reset(ha); | 934 | status = QLA_ERROR; |
| 916 | else | ||
| 917 | status = QLA_ERROR; | ||
| 918 | } | ||
| 919 | 935 | ||
| 920 | /* Flush any pending ddb changed AENs */ | 936 | /* Flush any pending ddb changed AENs */ |
| 921 | qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); | 937 | qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); |
| @@ -1527,11 +1543,9 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd) | |||
| 1527 | { | 1543 | { |
| 1528 | struct scsi_qla_host *ha = to_qla_host(cmd->device->host); | 1544 | struct scsi_qla_host *ha = to_qla_host(cmd->device->host); |
| 1529 | struct ddb_entry *ddb_entry = cmd->device->hostdata; | 1545 | struct ddb_entry *ddb_entry = cmd->device->hostdata; |
| 1530 | struct srb *sp; | ||
| 1531 | int ret = FAILED, stat; | 1546 | int ret = FAILED, stat; |
| 1532 | 1547 | ||
| 1533 | sp = (struct srb *) cmd->SCp.ptr; | 1548 | if (!ddb_entry) |
| 1534 | if (!sp || !ddb_entry) | ||
| 1535 | return ret; | 1549 | return ret; |
| 1536 | 1550 | ||
| 1537 | dev_info(&ha->pdev->dev, | 1551 | dev_info(&ha->pdev->dev, |
| @@ -1644,7 +1658,7 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd) | |||
| 1644 | ha = (struct scsi_qla_host *) cmd->device->host->hostdata; | 1658 | ha = (struct scsi_qla_host *) cmd->device->host->hostdata; |
| 1645 | 1659 | ||
| 1646 | dev_info(&ha->pdev->dev, | 1660 | dev_info(&ha->pdev->dev, |
| 1647 | "scsi(%ld:%d:%d:%d): ADAPTER RESET ISSUED.\n", ha->host_no, | 1661 | "scsi(%ld:%d:%d:%d): HOST RESET ISSUED.\n", ha->host_no, |
| 1648 | cmd->device->channel, cmd->device->id, cmd->device->lun); | 1662 | cmd->device->channel, cmd->device->id, cmd->device->lun); |
| 1649 | 1663 | ||
| 1650 | if (qla4xxx_wait_for_hba_online(ha) != QLA_SUCCESS) { | 1664 | if (qla4xxx_wait_for_hba_online(ha) != QLA_SUCCESS) { |
diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h index ab984cb89cea..6980cb279c81 100644 --- a/drivers/scsi/qla4xxx/ql4_version.h +++ b/drivers/scsi/qla4xxx/ql4_version.h | |||
| @@ -5,5 +5,5 @@ | |||
| 5 | * See LICENSE.qla4xxx for copyright and licensing details. | 5 | * See LICENSE.qla4xxx for copyright and licensing details. |
| 6 | */ | 6 | */ |
| 7 | 7 | ||
| 8 | #define QLA4XXX_DRIVER_VERSION "5.01.00-k8" | 8 | #define QLA4XXX_DRIVER_VERSION "5.01.00-k9" |
| 9 | 9 | ||
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 5616cd780ff3..b7b9fec67a98 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
| @@ -1840,6 +1840,18 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp) | |||
| 1840 | kfree(buffer); | 1840 | kfree(buffer); |
| 1841 | } | 1841 | } |
| 1842 | 1842 | ||
| 1843 | static int sd_try_extended_inquiry(struct scsi_device *sdp) | ||
| 1844 | { | ||
| 1845 | /* | ||
| 1846 | * Although VPD inquiries can go to SCSI-2 type devices, | ||
| 1847 | * some USB ones crash on receiving them, and the pages | ||
| 1848 | * we currently ask for are for SPC-3 and beyond | ||
| 1849 | */ | ||
| 1850 | if (sdp->scsi_level > SCSI_SPC_2) | ||
| 1851 | return 1; | ||
| 1852 | return 0; | ||
| 1853 | } | ||
| 1854 | |||
| 1843 | /** | 1855 | /** |
| 1844 | * sd_revalidate_disk - called the first time a new disk is seen, | 1856 | * sd_revalidate_disk - called the first time a new disk is seen, |
| 1845 | * performs disk spin up, read_capacity, etc. | 1857 | * performs disk spin up, read_capacity, etc. |
| @@ -1877,8 +1889,12 @@ static int sd_revalidate_disk(struct gendisk *disk) | |||
| 1877 | */ | 1889 | */ |
| 1878 | if (sdkp->media_present) { | 1890 | if (sdkp->media_present) { |
| 1879 | sd_read_capacity(sdkp, buffer); | 1891 | sd_read_capacity(sdkp, buffer); |
| 1880 | sd_read_block_limits(sdkp); | 1892 | |
| 1881 | sd_read_block_characteristics(sdkp); | 1893 | if (sd_try_extended_inquiry(sdp)) { |
| 1894 | sd_read_block_limits(sdkp); | ||
| 1895 | sd_read_block_characteristics(sdkp); | ||
| 1896 | } | ||
| 1897 | |||
| 1882 | sd_read_write_protect_flag(sdkp, buffer); | 1898 | sd_read_write_protect_flag(sdkp, buffer); |
| 1883 | sd_read_cache_type(sdkp, buffer); | 1899 | sd_read_cache_type(sdkp, buffer); |
| 1884 | sd_read_app_tag_own(sdkp, buffer); | 1900 | sd_read_app_tag_own(sdkp, buffer); |
