aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/ibmvscsi/ibmvfc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/ibmvscsi/ibmvfc.c')
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.c293
1 files changed, 196 insertions, 97 deletions
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 7650707a40de..44f202f33101 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -121,6 +121,7 @@ static const struct {
121 { IBMVFC_VIOS_FAILURE, IBMVFC_TRANS_CANCELLED, DID_ABORT, 0, 1, "transaction cancelled" }, 121 { IBMVFC_VIOS_FAILURE, IBMVFC_TRANS_CANCELLED, DID_ABORT, 0, 1, "transaction cancelled" },
122 { IBMVFC_VIOS_FAILURE, IBMVFC_TRANS_CANCELLED_IMPLICIT, DID_ABORT, 0, 1, "transaction cancelled implicit" }, 122 { IBMVFC_VIOS_FAILURE, IBMVFC_TRANS_CANCELLED_IMPLICIT, DID_ABORT, 0, 1, "transaction cancelled implicit" },
123 { IBMVFC_VIOS_FAILURE, IBMVFC_INSUFFICIENT_RESOURCE, DID_REQUEUE, 1, 1, "insufficient resources" }, 123 { IBMVFC_VIOS_FAILURE, IBMVFC_INSUFFICIENT_RESOURCE, DID_REQUEUE, 1, 1, "insufficient resources" },
124 { IBMVFC_VIOS_FAILURE, IBMVFC_PLOGI_REQUIRED, DID_ERROR, 0, 1, "port login required" },
124 { IBMVFC_VIOS_FAILURE, IBMVFC_COMMAND_FAILED, DID_ERROR, 1, 1, "command failed" }, 125 { IBMVFC_VIOS_FAILURE, IBMVFC_COMMAND_FAILED, DID_ERROR, 1, 1, "command failed" },
125 126
126 { IBMVFC_FC_FAILURE, IBMVFC_INVALID_ELS_CMD_CODE, DID_ERROR, 0, 1, "invalid ELS command code" }, 127 { IBMVFC_FC_FAILURE, IBMVFC_INVALID_ELS_CMD_CODE, DID_ERROR, 0, 1, "invalid ELS command code" },
@@ -278,13 +279,6 @@ static int ibmvfc_get_err_result(struct ibmvfc_cmd *vfc_cmd)
278 rsp->data.info.rsp_code)) 279 rsp->data.info.rsp_code))
279 return DID_ERROR << 16; 280 return DID_ERROR << 16;
280 281
281 if (!vfc_cmd->status) {
282 if (rsp->flags & FCP_RESID_OVER)
283 return rsp->scsi_status | (DID_ERROR << 16);
284 else
285 return rsp->scsi_status | (DID_OK << 16);
286 }
287
288 err = ibmvfc_get_err_index(vfc_cmd->status, vfc_cmd->error); 282 err = ibmvfc_get_err_index(vfc_cmd->status, vfc_cmd->error);
289 if (err >= 0) 283 if (err >= 0)
290 return rsp->scsi_status | (cmd_status[err].result << 16); 284 return rsp->scsi_status | (cmd_status[err].result << 16);
@@ -503,6 +497,7 @@ static void ibmvfc_set_host_action(struct ibmvfc_host *vhost,
503 case IBMVFC_HOST_ACTION_INIT: 497 case IBMVFC_HOST_ACTION_INIT:
504 case IBMVFC_HOST_ACTION_TGT_DEL: 498 case IBMVFC_HOST_ACTION_TGT_DEL:
505 case IBMVFC_HOST_ACTION_QUERY_TGTS: 499 case IBMVFC_HOST_ACTION_QUERY_TGTS:
500 case IBMVFC_HOST_ACTION_TGT_DEL_FAILED:
506 case IBMVFC_HOST_ACTION_TGT_ADD: 501 case IBMVFC_HOST_ACTION_TGT_ADD:
507 case IBMVFC_HOST_ACTION_NONE: 502 case IBMVFC_HOST_ACTION_NONE:
508 default: 503 default:
@@ -566,7 +561,7 @@ static void ibmvfc_init_host(struct ibmvfc_host *vhost, int relogin)
566 struct ibmvfc_target *tgt; 561 struct ibmvfc_target *tgt;
567 562
568 if (vhost->action == IBMVFC_HOST_ACTION_INIT_WAIT) { 563 if (vhost->action == IBMVFC_HOST_ACTION_INIT_WAIT) {
569 if (++vhost->init_retries > IBMVFC_MAX_INIT_RETRIES) { 564 if (++vhost->init_retries > IBMVFC_MAX_HOST_INIT_RETRIES) {
570 dev_err(vhost->dev, 565 dev_err(vhost->dev,
571 "Host initialization retries exceeded. Taking adapter offline\n"); 566 "Host initialization retries exceeded. Taking adapter offline\n");
572 ibmvfc_link_down(vhost, IBMVFC_HOST_OFFLINE); 567 ibmvfc_link_down(vhost, IBMVFC_HOST_OFFLINE);
@@ -765,6 +760,9 @@ static void ibmvfc_scsi_eh_done(struct ibmvfc_event *evt)
765 cmnd->scsi_done(cmnd); 760 cmnd->scsi_done(cmnd);
766 } 761 }
767 762
763 if (evt->eh_comp)
764 complete(evt->eh_comp);
765
768 ibmvfc_free_event(evt); 766 ibmvfc_free_event(evt);
769} 767}
770 768
@@ -847,11 +845,12 @@ static void ibmvfc_reset_host(struct ibmvfc_host *vhost)
847static void ibmvfc_retry_host_init(struct ibmvfc_host *vhost) 845static void ibmvfc_retry_host_init(struct ibmvfc_host *vhost)
848{ 846{
849 if (vhost->action == IBMVFC_HOST_ACTION_INIT_WAIT) { 847 if (vhost->action == IBMVFC_HOST_ACTION_INIT_WAIT) {
850 if (++vhost->init_retries > IBMVFC_MAX_INIT_RETRIES) { 848 vhost->delay_init = 1;
849 if (++vhost->init_retries > IBMVFC_MAX_HOST_INIT_RETRIES) {
851 dev_err(vhost->dev, 850 dev_err(vhost->dev,
852 "Host initialization retries exceeded. Taking adapter offline\n"); 851 "Host initialization retries exceeded. Taking adapter offline\n");
853 ibmvfc_link_down(vhost, IBMVFC_HOST_OFFLINE); 852 ibmvfc_link_down(vhost, IBMVFC_HOST_OFFLINE);
854 } else if (vhost->init_retries == IBMVFC_MAX_INIT_RETRIES) 853 } else if (vhost->init_retries == IBMVFC_MAX_HOST_INIT_RETRIES)
855 __ibmvfc_reset_host(vhost); 854 __ibmvfc_reset_host(vhost);
856 else 855 else
857 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT); 856 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT);
@@ -1252,6 +1251,7 @@ static void ibmvfc_init_event(struct ibmvfc_event *evt,
1252 evt->sync_iu = NULL; 1251 evt->sync_iu = NULL;
1253 evt->crq.format = format; 1252 evt->crq.format = format;
1254 evt->done = done; 1253 evt->done = done;
1254 evt->eh_comp = NULL;
1255} 1255}
1256 1256
1257/** 1257/**
@@ -1381,6 +1381,8 @@ static int ibmvfc_send_event(struct ibmvfc_event *evt,
1381 add_timer(&evt->timer); 1381 add_timer(&evt->timer);
1382 } 1382 }
1383 1383
1384 mb();
1385
1384 if ((rc = ibmvfc_send_crq(vhost, crq_as_u64[0], crq_as_u64[1]))) { 1386 if ((rc = ibmvfc_send_crq(vhost, crq_as_u64[0], crq_as_u64[1]))) {
1385 list_del(&evt->queue); 1387 list_del(&evt->queue);
1386 del_timer(&evt->timer); 1388 del_timer(&evt->timer);
@@ -1477,6 +1479,11 @@ static void ibmvfc_scsi_done(struct ibmvfc_event *evt)
1477 sense_len = SCSI_SENSE_BUFFERSIZE - rsp_len; 1479 sense_len = SCSI_SENSE_BUFFERSIZE - rsp_len;
1478 if ((rsp->flags & FCP_SNS_LEN_VALID) && rsp->fcp_sense_len && rsp_len <= 8) 1480 if ((rsp->flags & FCP_SNS_LEN_VALID) && rsp->fcp_sense_len && rsp_len <= 8)
1479 memcpy(cmnd->sense_buffer, rsp->data.sense + rsp_len, sense_len); 1481 memcpy(cmnd->sense_buffer, rsp->data.sense + rsp_len, sense_len);
1482 if ((vfc_cmd->status & IBMVFC_VIOS_FAILURE) && (vfc_cmd->error == IBMVFC_PLOGI_REQUIRED))
1483 ibmvfc_reinit_host(evt->vhost);
1484
1485 if (!cmnd->result && (!scsi_get_resid(cmnd) || (rsp->flags & FCP_RESID_OVER)))
1486 cmnd->result = (DID_ERROR << 16);
1480 1487
1481 ibmvfc_log_error(evt); 1488 ibmvfc_log_error(evt);
1482 } 1489 }
@@ -1489,6 +1496,9 @@ static void ibmvfc_scsi_done(struct ibmvfc_event *evt)
1489 cmnd->scsi_done(cmnd); 1496 cmnd->scsi_done(cmnd);
1490 } 1497 }
1491 1498
1499 if (evt->eh_comp)
1500 complete(evt->eh_comp);
1501
1492 ibmvfc_free_event(evt); 1502 ibmvfc_free_event(evt);
1493} 1503}
1494 1504
@@ -1627,7 +1637,7 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc)
1627 struct ibmvfc_host *vhost = shost_priv(sdev->host); 1637 struct ibmvfc_host *vhost = shost_priv(sdev->host);
1628 struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); 1638 struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
1629 struct ibmvfc_cmd *tmf; 1639 struct ibmvfc_cmd *tmf;
1630 struct ibmvfc_event *evt; 1640 struct ibmvfc_event *evt = NULL;
1631 union ibmvfc_iu rsp_iu; 1641 union ibmvfc_iu rsp_iu;
1632 struct ibmvfc_fcp_rsp *fc_rsp = &rsp_iu.cmd.rsp; 1642 struct ibmvfc_fcp_rsp *fc_rsp = &rsp_iu.cmd.rsp;
1633 int rsp_rc = -EBUSY; 1643 int rsp_rc = -EBUSY;
@@ -1789,7 +1799,8 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev)
1789static int ibmvfc_cancel_all(struct scsi_device *sdev, int type) 1799static int ibmvfc_cancel_all(struct scsi_device *sdev, int type)
1790{ 1800{
1791 struct ibmvfc_host *vhost = shost_priv(sdev->host); 1801 struct ibmvfc_host *vhost = shost_priv(sdev->host);
1792 struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); 1802 struct scsi_target *starget = scsi_target(sdev);
1803 struct fc_rport *rport = starget_to_rport(starget);
1793 struct ibmvfc_tmf *tmf; 1804 struct ibmvfc_tmf *tmf;
1794 struct ibmvfc_event *evt, *found_evt; 1805 struct ibmvfc_event *evt, *found_evt;
1795 union ibmvfc_iu rsp; 1806 union ibmvfc_iu rsp;
@@ -1827,7 +1838,7 @@ static int ibmvfc_cancel_all(struct scsi_device *sdev, int type)
1827 int_to_scsilun(sdev->lun, &tmf->lun); 1838 int_to_scsilun(sdev->lun, &tmf->lun);
1828 tmf->flags = (type | IBMVFC_TMF_LUA_VALID); 1839 tmf->flags = (type | IBMVFC_TMF_LUA_VALID);
1829 tmf->cancel_key = (unsigned long)sdev->hostdata; 1840 tmf->cancel_key = (unsigned long)sdev->hostdata;
1830 tmf->my_cancel_key = (IBMVFC_TMF_CANCEL_KEY | (unsigned long)sdev->hostdata); 1841 tmf->my_cancel_key = (unsigned long)starget->hostdata;
1831 1842
1832 evt->sync_iu = &rsp; 1843 evt->sync_iu = &rsp;
1833 init_completion(&evt->comp); 1844 init_completion(&evt->comp);
@@ -1859,6 +1870,91 @@ static int ibmvfc_cancel_all(struct scsi_device *sdev, int type)
1859} 1870}
1860 1871
1861/** 1872/**
1873 * ibmvfc_match_target - Match function for specified target
1874 * @evt: ibmvfc event struct
1875 * @device: device to match (starget)
1876 *
1877 * Returns:
1878 * 1 if event matches starget / 0 if event does not match starget
1879 **/
1880static int ibmvfc_match_target(struct ibmvfc_event *evt, void *device)
1881{
1882 if (evt->cmnd && scsi_target(evt->cmnd->device) == device)
1883 return 1;
1884 return 0;
1885}
1886
1887/**
1888 * ibmvfc_match_lun - Match function for specified LUN
1889 * @evt: ibmvfc event struct
1890 * @device: device to match (sdev)
1891 *
1892 * Returns:
1893 * 1 if event matches sdev / 0 if event does not match sdev
1894 **/
1895static int ibmvfc_match_lun(struct ibmvfc_event *evt, void *device)
1896{
1897 if (evt->cmnd && evt->cmnd->device == device)
1898 return 1;
1899 return 0;
1900}
1901
1902/**
1903 * ibmvfc_wait_for_ops - Wait for ops to complete
1904 * @vhost: ibmvfc host struct
1905 * @device: device to match (starget or sdev)
1906 * @match: match function
1907 *
1908 * Returns:
1909 * SUCCESS / FAILED
1910 **/
1911static int ibmvfc_wait_for_ops(struct ibmvfc_host *vhost, void *device,
1912 int (*match) (struct ibmvfc_event *, void *))
1913{
1914 struct ibmvfc_event *evt;
1915 DECLARE_COMPLETION_ONSTACK(comp);
1916 int wait;
1917 unsigned long flags;
1918 signed long timeout = init_timeout * HZ;
1919
1920 ENTER;
1921 do {
1922 wait = 0;
1923 spin_lock_irqsave(vhost->host->host_lock, flags);
1924 list_for_each_entry(evt, &vhost->sent, queue) {
1925 if (match(evt, device)) {
1926 evt->eh_comp = &comp;
1927 wait++;
1928 }
1929 }
1930 spin_unlock_irqrestore(vhost->host->host_lock, flags);
1931
1932 if (wait) {
1933 timeout = wait_for_completion_timeout(&comp, timeout);
1934
1935 if (!timeout) {
1936 wait = 0;
1937 spin_lock_irqsave(vhost->host->host_lock, flags);
1938 list_for_each_entry(evt, &vhost->sent, queue) {
1939 if (match(evt, device)) {
1940 evt->eh_comp = NULL;
1941 wait++;
1942 }
1943 }
1944 spin_unlock_irqrestore(vhost->host->host_lock, flags);
1945 if (wait)
1946 dev_err(vhost->dev, "Timed out waiting for aborted commands\n");
1947 LEAVE;
1948 return wait ? FAILED : SUCCESS;
1949 }
1950 }
1951 } while (wait);
1952
1953 LEAVE;
1954 return SUCCESS;
1955}
1956
1957/**
1862 * ibmvfc_eh_abort_handler - Abort a command 1958 * ibmvfc_eh_abort_handler - Abort a command
1863 * @cmd: scsi command to abort 1959 * @cmd: scsi command to abort
1864 * 1960 *
@@ -1867,29 +1963,21 @@ static int ibmvfc_cancel_all(struct scsi_device *sdev, int type)
1867 **/ 1963 **/
1868static int ibmvfc_eh_abort_handler(struct scsi_cmnd *cmd) 1964static int ibmvfc_eh_abort_handler(struct scsi_cmnd *cmd)
1869{ 1965{
1870 struct ibmvfc_host *vhost = shost_priv(cmd->device->host); 1966 struct scsi_device *sdev = cmd->device;
1871 struct ibmvfc_event *evt, *pos; 1967 struct ibmvfc_host *vhost = shost_priv(sdev->host);
1872 int cancel_rc, abort_rc; 1968 int cancel_rc, abort_rc;
1873 unsigned long flags; 1969 int rc = FAILED;
1874 1970
1875 ENTER; 1971 ENTER;
1876 ibmvfc_wait_while_resetting(vhost); 1972 ibmvfc_wait_while_resetting(vhost);
1877 cancel_rc = ibmvfc_cancel_all(cmd->device, IBMVFC_TMF_ABORT_TASK_SET); 1973 cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET);
1878 abort_rc = ibmvfc_abort_task_set(cmd->device); 1974 abort_rc = ibmvfc_abort_task_set(sdev);
1879 1975
1880 if (!cancel_rc && !abort_rc) { 1976 if (!cancel_rc && !abort_rc)
1881 spin_lock_irqsave(vhost->host->host_lock, flags); 1977 rc = ibmvfc_wait_for_ops(vhost, sdev, ibmvfc_match_lun);
1882 list_for_each_entry_safe(evt, pos, &vhost->sent, queue) {
1883 if (evt->cmnd && evt->cmnd->device == cmd->device)
1884 ibmvfc_fail_request(evt, DID_ABORT);
1885 }
1886 spin_unlock_irqrestore(vhost->host->host_lock, flags);
1887 LEAVE;
1888 return SUCCESS;
1889 }
1890 1978
1891 LEAVE; 1979 LEAVE;
1892 return FAILED; 1980 return rc;
1893} 1981}
1894 1982
1895/** 1983/**
@@ -1901,29 +1989,21 @@ static int ibmvfc_eh_abort_handler(struct scsi_cmnd *cmd)
1901 **/ 1989 **/
1902static int ibmvfc_eh_device_reset_handler(struct scsi_cmnd *cmd) 1990static int ibmvfc_eh_device_reset_handler(struct scsi_cmnd *cmd)
1903{ 1991{
1904 struct ibmvfc_host *vhost = shost_priv(cmd->device->host); 1992 struct scsi_device *sdev = cmd->device;
1905 struct ibmvfc_event *evt, *pos; 1993 struct ibmvfc_host *vhost = shost_priv(sdev->host);
1906 int cancel_rc, reset_rc; 1994 int cancel_rc, reset_rc;
1907 unsigned long flags; 1995 int rc = FAILED;
1908 1996
1909 ENTER; 1997 ENTER;
1910 ibmvfc_wait_while_resetting(vhost); 1998 ibmvfc_wait_while_resetting(vhost);
1911 cancel_rc = ibmvfc_cancel_all(cmd->device, IBMVFC_TMF_LUN_RESET); 1999 cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_LUN_RESET);
1912 reset_rc = ibmvfc_reset_device(cmd->device, IBMVFC_LUN_RESET, "LUN"); 2000 reset_rc = ibmvfc_reset_device(sdev, IBMVFC_LUN_RESET, "LUN");
1913 2001
1914 if (!cancel_rc && !reset_rc) { 2002 if (!cancel_rc && !reset_rc)
1915 spin_lock_irqsave(vhost->host->host_lock, flags); 2003 rc = ibmvfc_wait_for_ops(vhost, sdev, ibmvfc_match_lun);
1916 list_for_each_entry_safe(evt, pos, &vhost->sent, queue) {
1917 if (evt->cmnd && evt->cmnd->device == cmd->device)
1918 ibmvfc_fail_request(evt, DID_ABORT);
1919 }
1920 spin_unlock_irqrestore(vhost->host->host_lock, flags);
1921 LEAVE;
1922 return SUCCESS;
1923 }
1924 2004
1925 LEAVE; 2005 LEAVE;
1926 return FAILED; 2006 return rc;
1927} 2007}
1928 2008
1929/** 2009/**
@@ -1959,31 +2039,23 @@ static void ibmvfc_dev_abort_all(struct scsi_device *sdev, void *data)
1959 **/ 2039 **/
1960static int ibmvfc_eh_target_reset_handler(struct scsi_cmnd *cmd) 2040static int ibmvfc_eh_target_reset_handler(struct scsi_cmnd *cmd)
1961{ 2041{
1962 struct ibmvfc_host *vhost = shost_priv(cmd->device->host); 2042 struct scsi_device *sdev = cmd->device;
1963 struct scsi_target *starget = scsi_target(cmd->device); 2043 struct ibmvfc_host *vhost = shost_priv(sdev->host);
1964 struct ibmvfc_event *evt, *pos; 2044 struct scsi_target *starget = scsi_target(sdev);
1965 int reset_rc; 2045 int reset_rc;
2046 int rc = FAILED;
1966 unsigned long cancel_rc = 0; 2047 unsigned long cancel_rc = 0;
1967 unsigned long flags;
1968 2048
1969 ENTER; 2049 ENTER;
1970 ibmvfc_wait_while_resetting(vhost); 2050 ibmvfc_wait_while_resetting(vhost);
1971 starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all); 2051 starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all);
1972 reset_rc = ibmvfc_reset_device(cmd->device, IBMVFC_TARGET_RESET, "target"); 2052 reset_rc = ibmvfc_reset_device(sdev, IBMVFC_TARGET_RESET, "target");
1973 2053
1974 if (!cancel_rc && !reset_rc) { 2054 if (!cancel_rc && !reset_rc)
1975 spin_lock_irqsave(vhost->host->host_lock, flags); 2055 rc = ibmvfc_wait_for_ops(vhost, starget, ibmvfc_match_target);
1976 list_for_each_entry_safe(evt, pos, &vhost->sent, queue) {
1977 if (evt->cmnd && scsi_target(evt->cmnd->device) == starget)
1978 ibmvfc_fail_request(evt, DID_ABORT);
1979 }
1980 spin_unlock_irqrestore(vhost->host->host_lock, flags);
1981 LEAVE;
1982 return SUCCESS;
1983 }
1984 2056
1985 LEAVE; 2057 LEAVE;
1986 return FAILED; 2058 return rc;
1987} 2059}
1988 2060
1989/** 2061/**
@@ -2013,23 +2085,18 @@ static void ibmvfc_terminate_rport_io(struct fc_rport *rport)
2013 struct scsi_target *starget = to_scsi_target(&rport->dev); 2085 struct scsi_target *starget = to_scsi_target(&rport->dev);
2014 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 2086 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2015 struct ibmvfc_host *vhost = shost_priv(shost); 2087 struct ibmvfc_host *vhost = shost_priv(shost);
2016 struct ibmvfc_event *evt, *pos;
2017 unsigned long cancel_rc = 0; 2088 unsigned long cancel_rc = 0;
2018 unsigned long abort_rc = 0; 2089 unsigned long abort_rc = 0;
2019 unsigned long flags; 2090 int rc = FAILED;
2020 2091
2021 ENTER; 2092 ENTER;
2022 starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all); 2093 starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all);
2023 starget_for_each_device(starget, &abort_rc, ibmvfc_dev_abort_all); 2094 starget_for_each_device(starget, &abort_rc, ibmvfc_dev_abort_all);
2024 2095
2025 if (!cancel_rc && !abort_rc) { 2096 if (!cancel_rc && !abort_rc)
2026 spin_lock_irqsave(shost->host_lock, flags); 2097 rc = ibmvfc_wait_for_ops(vhost, starget, ibmvfc_match_target);
2027 list_for_each_entry_safe(evt, pos, &vhost->sent, queue) { 2098
2028 if (evt->cmnd && scsi_target(evt->cmnd->device) == starget) 2099 if (rc == FAILED)
2029 ibmvfc_fail_request(evt, DID_ABORT);
2030 }
2031 spin_unlock_irqrestore(shost->host_lock, flags);
2032 } else
2033 ibmvfc_issue_fc_host_lip(shost); 2100 ibmvfc_issue_fc_host_lip(shost);
2034 LEAVE; 2101 LEAVE;
2035} 2102}
@@ -2089,15 +2156,17 @@ static void ibmvfc_handle_async(struct ibmvfc_async_crq *crq,
2089 case IBMVFC_AE_LINK_UP: 2156 case IBMVFC_AE_LINK_UP:
2090 case IBMVFC_AE_RESUME: 2157 case IBMVFC_AE_RESUME:
2091 vhost->events_to_log |= IBMVFC_AE_LINKUP; 2158 vhost->events_to_log |= IBMVFC_AE_LINKUP;
2092 ibmvfc_init_host(vhost, 1); 2159 vhost->delay_init = 1;
2160 __ibmvfc_reset_host(vhost);
2093 break; 2161 break;
2094 case IBMVFC_AE_SCN_FABRIC: 2162 case IBMVFC_AE_SCN_FABRIC:
2163 case IBMVFC_AE_SCN_DOMAIN:
2095 vhost->events_to_log |= IBMVFC_AE_RSCN; 2164 vhost->events_to_log |= IBMVFC_AE_RSCN;
2096 ibmvfc_init_host(vhost, 1); 2165 vhost->delay_init = 1;
2166 __ibmvfc_reset_host(vhost);
2097 break; 2167 break;
2098 case IBMVFC_AE_SCN_NPORT: 2168 case IBMVFC_AE_SCN_NPORT:
2099 case IBMVFC_AE_SCN_GROUP: 2169 case IBMVFC_AE_SCN_GROUP:
2100 case IBMVFC_AE_SCN_DOMAIN:
2101 vhost->events_to_log |= IBMVFC_AE_RSCN; 2170 vhost->events_to_log |= IBMVFC_AE_RSCN;
2102 case IBMVFC_AE_ELS_LOGO: 2171 case IBMVFC_AE_ELS_LOGO:
2103 case IBMVFC_AE_ELS_PRLO: 2172 case IBMVFC_AE_ELS_PRLO:
@@ -2263,6 +2332,28 @@ static int ibmvfc_slave_alloc(struct scsi_device *sdev)
2263} 2332}
2264 2333
2265/** 2334/**
2335 * ibmvfc_target_alloc - Setup the target's task set value
2336 * @starget: struct scsi_target
2337 *
2338 * Set the target's task set value so that error handling works as
2339 * expected.
2340 *
2341 * Returns:
2342 * 0 on success / -ENXIO if device does not exist
2343 **/
2344static int ibmvfc_target_alloc(struct scsi_target *starget)
2345{
2346 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2347 struct ibmvfc_host *vhost = shost_priv(shost);
2348 unsigned long flags = 0;
2349
2350 spin_lock_irqsave(shost->host_lock, flags);
2351 starget->hostdata = (void *)(unsigned long)vhost->task_set++;
2352 spin_unlock_irqrestore(shost->host_lock, flags);
2353 return 0;
2354}
2355
2356/**
2266 * ibmvfc_slave_configure - Configure the device 2357 * ibmvfc_slave_configure - Configure the device
2267 * @sdev: struct scsi_device device to configure 2358 * @sdev: struct scsi_device device to configure
2268 * 2359 *
@@ -2541,6 +2632,7 @@ static struct scsi_host_template driver_template = {
2541 .eh_host_reset_handler = ibmvfc_eh_host_reset_handler, 2632 .eh_host_reset_handler = ibmvfc_eh_host_reset_handler,
2542 .slave_alloc = ibmvfc_slave_alloc, 2633 .slave_alloc = ibmvfc_slave_alloc,
2543 .slave_configure = ibmvfc_slave_configure, 2634 .slave_configure = ibmvfc_slave_configure,
2635 .target_alloc = ibmvfc_target_alloc,
2544 .scan_finished = ibmvfc_scan_finished, 2636 .scan_finished = ibmvfc_scan_finished,
2545 .change_queue_depth = ibmvfc_change_queue_depth, 2637 .change_queue_depth = ibmvfc_change_queue_depth,
2546 .change_queue_type = ibmvfc_change_queue_type, 2638 .change_queue_type = ibmvfc_change_queue_type,
@@ -2637,7 +2729,7 @@ static irqreturn_t ibmvfc_interrupt(int irq, void *dev_instance)
2637 } else if ((async = ibmvfc_next_async_crq(vhost)) != NULL) { 2729 } else if ((async = ibmvfc_next_async_crq(vhost)) != NULL) {
2638 vio_disable_interrupts(vdev); 2730 vio_disable_interrupts(vdev);
2639 ibmvfc_handle_async(async, vhost); 2731 ibmvfc_handle_async(async, vhost);
2640 crq->valid = 0; 2732 async->valid = 0;
2641 } else 2733 } else
2642 done = 1; 2734 done = 1;
2643 } 2735 }
@@ -2669,7 +2761,7 @@ static void ibmvfc_init_tgt(struct ibmvfc_target *tgt,
2669static void ibmvfc_retry_tgt_init(struct ibmvfc_target *tgt, 2761static void ibmvfc_retry_tgt_init(struct ibmvfc_target *tgt,
2670 void (*job_step) (struct ibmvfc_target *)) 2762 void (*job_step) (struct ibmvfc_target *))
2671{ 2763{
2672 if (++tgt->init_retries > IBMVFC_MAX_INIT_RETRIES) { 2764 if (++tgt->init_retries > IBMVFC_MAX_TGT_INIT_RETRIES) {
2673 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); 2765 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
2674 wake_up(&tgt->vhost->work_wait_q); 2766 wake_up(&tgt->vhost->work_wait_q);
2675 } else 2767 } else
@@ -2708,6 +2800,8 @@ static void ibmvfc_tgt_prli_done(struct ibmvfc_event *evt)
2708 rsp->status, rsp->error, status); 2800 rsp->status, rsp->error, status);
2709 if (ibmvfc_retry_cmd(rsp->status, rsp->error)) 2801 if (ibmvfc_retry_cmd(rsp->status, rsp->error))
2710 ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_prli); 2802 ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_prli);
2803 else
2804 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
2711 break; 2805 break;
2712 }; 2806 };
2713 2807
@@ -2802,6 +2896,8 @@ static void ibmvfc_tgt_plogi_done(struct ibmvfc_event *evt)
2802 2896
2803 if (ibmvfc_retry_cmd(rsp->status, rsp->error)) 2897 if (ibmvfc_retry_cmd(rsp->status, rsp->error))
2804 ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_plogi); 2898 ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_plogi);
2899 else
2900 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
2805 break; 2901 break;
2806 }; 2902 };
2807 2903
@@ -3093,6 +3189,8 @@ static void ibmvfc_tgt_query_target_done(struct ibmvfc_event *evt)
3093 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); 3189 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
3094 else if (ibmvfc_retry_cmd(rsp->status, rsp->error)) 3190 else if (ibmvfc_retry_cmd(rsp->status, rsp->error))
3095 ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_query_target); 3191 ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_query_target);
3192 else
3193 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
3096 break; 3194 break;
3097 }; 3195 };
3098 3196
@@ -3423,6 +3521,7 @@ static int __ibmvfc_work_to_do(struct ibmvfc_host *vhost)
3423 case IBMVFC_HOST_ACTION_ALLOC_TGTS: 3521 case IBMVFC_HOST_ACTION_ALLOC_TGTS:
3424 case IBMVFC_HOST_ACTION_TGT_ADD: 3522 case IBMVFC_HOST_ACTION_TGT_ADD:
3425 case IBMVFC_HOST_ACTION_TGT_DEL: 3523 case IBMVFC_HOST_ACTION_TGT_DEL:
3524 case IBMVFC_HOST_ACTION_TGT_DEL_FAILED:
3426 case IBMVFC_HOST_ACTION_QUERY: 3525 case IBMVFC_HOST_ACTION_QUERY:
3427 default: 3526 default:
3428 break; 3527 break;
@@ -3519,7 +3618,13 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost)
3519 break; 3618 break;
3520 case IBMVFC_HOST_ACTION_INIT: 3619 case IBMVFC_HOST_ACTION_INIT:
3521 BUG_ON(vhost->state != IBMVFC_INITIALIZING); 3620 BUG_ON(vhost->state != IBMVFC_INITIALIZING);
3522 vhost->job_step(vhost); 3621 if (vhost->delay_init) {
3622 vhost->delay_init = 0;
3623 spin_unlock_irqrestore(vhost->host->host_lock, flags);
3624 ssleep(15);
3625 return;
3626 } else
3627 vhost->job_step(vhost);
3523 break; 3628 break;
3524 case IBMVFC_HOST_ACTION_QUERY: 3629 case IBMVFC_HOST_ACTION_QUERY:
3525 list_for_each_entry(tgt, &vhost->targets, queue) 3630 list_for_each_entry(tgt, &vhost->targets, queue)
@@ -3538,6 +3643,7 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost)
3538 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_TGT_DEL); 3643 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_TGT_DEL);
3539 break; 3644 break;
3540 case IBMVFC_HOST_ACTION_TGT_DEL: 3645 case IBMVFC_HOST_ACTION_TGT_DEL:
3646 case IBMVFC_HOST_ACTION_TGT_DEL_FAILED:
3541 list_for_each_entry(tgt, &vhost->targets, queue) { 3647 list_for_each_entry(tgt, &vhost->targets, queue) {
3542 if (tgt->action == IBMVFC_TGT_ACTION_DEL_RPORT) { 3648 if (tgt->action == IBMVFC_TGT_ACTION_DEL_RPORT) {
3543 tgt_dbg(tgt, "Deleting rport\n"); 3649 tgt_dbg(tgt, "Deleting rport\n");
@@ -3553,8 +3659,17 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost)
3553 } 3659 }
3554 3660
3555 if (vhost->state == IBMVFC_INITIALIZING) { 3661 if (vhost->state == IBMVFC_INITIALIZING) {
3556 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT); 3662 if (vhost->action == IBMVFC_HOST_ACTION_TGT_DEL_FAILED) {
3557 vhost->job_step = ibmvfc_discover_targets; 3663 ibmvfc_set_host_state(vhost, IBMVFC_ACTIVE);
3664 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_TGT_ADD);
3665 vhost->init_retries = 0;
3666 spin_unlock_irqrestore(vhost->host->host_lock, flags);
3667 scsi_unblock_requests(vhost->host);
3668 return;
3669 } else {
3670 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT);
3671 vhost->job_step = ibmvfc_discover_targets;
3672 }
3558 } else { 3673 } else {
3559 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_NONE); 3674 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_NONE);
3560 spin_unlock_irqrestore(vhost->host->host_lock, flags); 3675 spin_unlock_irqrestore(vhost->host->host_lock, flags);
@@ -3577,14 +3692,8 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost)
3577 } 3692 }
3578 } 3693 }
3579 3694
3580 if (!ibmvfc_dev_init_to_do(vhost)) { 3695 if (!ibmvfc_dev_init_to_do(vhost))
3581 ibmvfc_set_host_state(vhost, IBMVFC_ACTIVE); 3696 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_TGT_DEL_FAILED);
3582 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_TGT_ADD);
3583 vhost->init_retries = 0;
3584 spin_unlock_irqrestore(vhost->host->host_lock, flags);
3585 scsi_unblock_requests(vhost->host);
3586 return;
3587 }
3588 break; 3697 break;
3589 case IBMVFC_HOST_ACTION_TGT_ADD: 3698 case IBMVFC_HOST_ACTION_TGT_ADD:
3590 list_for_each_entry(tgt, &vhost->targets, queue) { 3699 list_for_each_entry(tgt, &vhost->targets, queue) {
@@ -3592,16 +3701,6 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost)
3592 spin_unlock_irqrestore(vhost->host->host_lock, flags); 3701 spin_unlock_irqrestore(vhost->host->host_lock, flags);
3593 ibmvfc_tgt_add_rport(tgt); 3702 ibmvfc_tgt_add_rport(tgt);
3594 return; 3703 return;
3595 } else if (tgt->action == IBMVFC_TGT_ACTION_DEL_RPORT) {
3596 tgt_dbg(tgt, "Deleting rport\n");
3597 rport = tgt->rport;
3598 tgt->rport = NULL;
3599 list_del(&tgt->queue);
3600 spin_unlock_irqrestore(vhost->host->host_lock, flags);
3601 if (rport)
3602 fc_remote_port_delete(rport);
3603 kref_put(&tgt->kref, ibmvfc_release_tgt);
3604 return;
3605 } 3704 }
3606 } 3705 }
3607 3706