aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2011-05-02 16:59:25 -0400
committerDan Williams <dan.j.williams@intel.com>2011-07-03 07:04:46 -0400
commitd06b487b78f28a02efdcdcc9ec295bf230b9d0e8 (patch)
tree7be7614402ec7cd7f3b90455d2162b62b28418de /drivers
parent5b3f2bd877382eaf4b5a7d90fdec72ef14b9ec97 (diff)
isci: implement I_T_nexus_reset
This is a requirement for 2.6.39's new libata eh. Still some questions about lldd_dev_gone racing against dev->lldd_dev lookups, but we are at least no more broken than mvsas in this regard. We also short-circuit I_T_nexus_reset invocations from the device discovery path (IDEV_EH similar to MVS_DEV_EH) to filter out the resulting domain rediscoveries triggered by the reset. Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/isci/remote_device.c1
-rw-r--r--drivers/scsi/isci/remote_device.h1
-rw-r--r--drivers/scsi/isci/task.c138
3 files changed, 76 insertions, 64 deletions
diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c
index 15c1e6c3b223..ee6fe1db8f99 100644
--- a/drivers/scsi/isci/remote_device.c
+++ b/drivers/scsi/isci/remote_device.c
@@ -891,6 +891,7 @@ static void isci_remote_device_deconstruct(struct isci_host *ihost, struct isci_
891 891
892 clear_bit(IDEV_START_PENDING, &idev->flags); 892 clear_bit(IDEV_START_PENDING, &idev->flags);
893 clear_bit(IDEV_STOP_PENDING, &idev->flags); 893 clear_bit(IDEV_STOP_PENDING, &idev->flags);
894 clear_bit(IDEV_EH, &idev->flags);
894 wake_up(&ihost->eventq); 895 wake_up(&ihost->eventq);
895} 896}
896 897
diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h
index c7db4998b8f9..2e433b7f16b3 100644
--- a/drivers/scsi/isci/remote_device.h
+++ b/drivers/scsi/isci/remote_device.h
@@ -134,6 +134,7 @@ struct isci_remote_device {
134 #define IDEV_START_PENDING 0 134 #define IDEV_START_PENDING 0
135 #define IDEV_STOP_PENDING 1 135 #define IDEV_STOP_PENDING 1
136 #define IDEV_ALLOCATED 2 136 #define IDEV_ALLOCATED 2
137 #define IDEV_EH 3
137 unsigned long flags; 138 unsigned long flags;
138 struct isci_port *isci_port; 139 struct isci_port *isci_port;
139 struct domain_device *domain_dev; 140 struct domain_device *domain_dev;
diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c
index 8449d8abd66a..3a3f54677e5b 100644
--- a/drivers/scsi/isci/task.c
+++ b/drivers/scsi/isci/task.c
@@ -1022,9 +1022,11 @@ int isci_task_lu_reset(struct domain_device *domain_device, u8 *lun)
1022 "%s: domain_device=%p, isci_host=%p; isci_device=%p\n", 1022 "%s: domain_device=%p, isci_host=%p; isci_device=%p\n",
1023 __func__, domain_device, isci_host, isci_device); 1023 __func__, domain_device, isci_host, isci_device);
1024 1024
1025 if (isci_device != NULL) 1025 if (isci_device != NULL) {
1026 device_stopping = (isci_device->status == isci_stopping) 1026 device_stopping = (isci_device->status == isci_stopping)
1027 || (isci_device->status == isci_stopped); 1027 || (isci_device->status == isci_stopped);
1028 set_bit(IDEV_EH, &isci_device->flags);
1029 }
1028 1030
1029 /* If there is a device reset pending on any request in the 1031 /* If there is a device reset pending on any request in the
1030 * device's list, fail this LUN reset request in order to 1032 * device's list, fail this LUN reset request in order to
@@ -1069,12 +1071,6 @@ int isci_task_clear_nexus_ha(struct sas_ha_struct *ha)
1069 return TMF_RESP_FUNC_FAILED; 1071 return TMF_RESP_FUNC_FAILED;
1070} 1072}
1071 1073
1072int isci_task_I_T_nexus_reset(struct domain_device *dev)
1073{
1074 return TMF_RESP_FUNC_FAILED;
1075}
1076
1077
1078/* Task Management Functions. Must be called from process context. */ 1074/* Task Management Functions. Must be called from process context. */
1079 1075
1080/** 1076/**
@@ -1171,6 +1167,12 @@ int isci_task_abort_task(struct sas_task *task)
1171 device_stopping = (isci_device->status == isci_stopping) 1167 device_stopping = (isci_device->status == isci_stopping)
1172 || (isci_device->status == isci_stopped); 1168 || (isci_device->status == isci_stopped);
1173 1169
1170 /* XXX need to fix device lookup lifetime (needs to be done
1171 * under scic_lock, among other things...), but for now assume
1172 * the device is available like the above code
1173 */
1174 set_bit(IDEV_EH, &isci_device->flags);
1175
1174 /* This version of the driver will fail abort requests for 1176 /* This version of the driver will fail abort requests for
1175 * SATA/STP. Failing the abort request this way will cause the 1177 * SATA/STP. Failing the abort request this way will cause the
1176 * SCSI error handler thread to escalate to LUN reset 1178 * SCSI error handler thread to escalate to LUN reset
@@ -1481,86 +1483,94 @@ isci_task_request_complete(struct isci_host *ihost,
1481 complete(tmf_complete); 1483 complete(tmf_complete);
1482} 1484}
1483 1485
1484/** 1486static int isci_reset_device(struct domain_device *dev, int hard_reset)
1485 * isci_bus_reset_handler() - This function performs a target reset of the
1486 * device referenced by "cmd'. This function is exported through the
1487 * "struct scsi_host_template" structure such that it is called when an I/O
1488 * recovery process has escalated to a target reset. Note that this function
1489 * is called from the scsi error handler event thread, so may block on calls.
1490 * @scsi_cmd: This parameter specifies the target to be reset.
1491 *
1492 * SUCCESS if the reset process was successful, else FAILED.
1493 */
1494int isci_bus_reset_handler(struct scsi_cmnd *cmd)
1495{ 1487{
1496 struct domain_device *dev = cmd_to_domain_dev(cmd); 1488 struct isci_remote_device *idev = dev->lldd_dev;
1497 struct isci_host *isci_host = dev_to_ihost(dev); 1489 struct sas_phy *phy = sas_find_local_phy(dev);
1498 unsigned long flags = 0; 1490 struct isci_host *ihost = dev_to_ihost(dev);
1499 enum sci_status status; 1491 enum sci_status status;
1500 int base_status; 1492 unsigned long flags;
1501 struct isci_remote_device *isci_dev = dev->lldd_dev; 1493 int rc;
1502 1494
1503 dev_dbg(&isci_host->pdev->dev, 1495 dev_dbg(&ihost->pdev->dev, "%s: idev %p\n", __func__, idev);
1504 "%s: cmd %p, isci_dev %p\n",
1505 __func__, cmd, isci_dev);
1506 1496
1507 if (!isci_dev) { 1497 if (!idev) {
1508 dev_warn(&isci_host->pdev->dev, 1498 dev_warn(&ihost->pdev->dev,
1509 "%s: isci_dev is GONE!\n", 1499 "%s: idev is GONE!\n",
1510 __func__); 1500 __func__);
1511 1501
1512 return TMF_RESP_FUNC_COMPLETE; /* Nothing to reset. */ 1502 return TMF_RESP_FUNC_COMPLETE; /* Nothing to reset. */
1513 } 1503 }
1514 1504
1515 spin_lock_irqsave(&isci_host->scic_lock, flags); 1505 spin_lock_irqsave(&ihost->scic_lock, flags);
1516 status = scic_remote_device_reset(&isci_dev->sci); 1506 status = scic_remote_device_reset(&idev->sci);
1517 if (status != SCI_SUCCESS) { 1507 if (status != SCI_SUCCESS) {
1518 spin_unlock_irqrestore(&isci_host->scic_lock, flags); 1508 spin_unlock_irqrestore(&ihost->scic_lock, flags);
1519 1509
1520 scmd_printk(KERN_WARNING, cmd, 1510 dev_warn(&ihost->pdev->dev,
1521 "%s: scic_remote_device_reset(%p) returned %d!\n", 1511 "%s: scic_remote_device_reset(%p) returned %d!\n",
1522 __func__, isci_dev, status); 1512 __func__, idev, status);
1523 1513
1524 return TMF_RESP_FUNC_FAILED; 1514 return TMF_RESP_FUNC_FAILED;
1525 } 1515 }
1526 spin_unlock_irqrestore(&isci_host->scic_lock, flags); 1516 spin_unlock_irqrestore(&ihost->scic_lock, flags);
1527 1517
1528 /* Make sure all pending requests are able to be fully terminated. */ 1518 /* Make sure all pending requests are able to be fully terminated. */
1529 isci_device_clear_reset_pending(isci_host, isci_dev); 1519 isci_device_clear_reset_pending(ihost, idev);
1530 1520
1531 /* Terminate in-progress I/O now. */ 1521 rc = sas_phy_reset(phy, hard_reset);
1532 isci_remote_device_nuke_requests(isci_host, isci_dev); 1522 msleep(2000); /* just like mvsas */
1533 1523
1534 /* Call into the libsas default handler (which calls sas_phy_reset). */ 1524 /* Terminate in-progress I/O now. */
1535 base_status = sas_eh_bus_reset_handler(cmd); 1525 isci_remote_device_nuke_requests(ihost, idev);
1536 1526
1537 if (base_status != SUCCESS) { 1527 spin_lock_irqsave(&ihost->scic_lock, flags);
1528 status = scic_remote_device_reset_complete(&idev->sci);
1529 spin_unlock_irqrestore(&ihost->scic_lock, flags);
1538 1530
1539 /* There can be cases where the resets to individual devices 1531 if (status != SCI_SUCCESS) {
1540 * behind an expander will fail because of an unplug of the 1532 dev_warn(&ihost->pdev->dev,
1541 * expander itself. 1533 "%s: scic_remote_device_reset_complete(%p) "
1542 */ 1534 "returned %d!\n", __func__, idev, status);
1543 scmd_printk(KERN_WARNING, cmd,
1544 "%s: sas_eh_bus_reset_handler(%p) returned %d!\n",
1545 __func__, cmd, base_status);
1546 } 1535 }
1547 1536
1548 /* WHAT TO DO HERE IF sas_phy_reset FAILS? */ 1537 dev_dbg(&ihost->pdev->dev, "%s: idev %p complete.\n", __func__, idev);
1549 spin_lock_irqsave(&isci_host->scic_lock, flags);
1550 status = scic_remote_device_reset_complete(&isci_dev->sci);
1551 spin_unlock_irqrestore(&isci_host->scic_lock, flags);
1552 1538
1553 if (status != SCI_SUCCESS) { 1539 return rc;
1554 scmd_printk(KERN_WARNING, cmd, 1540}
1555 "%s: scic_remote_device_reset_complete(%p) "
1556 "returned %d!\n",
1557 __func__, isci_dev, status);
1558 }
1559 /* WHAT TO DO HERE IF scic_remote_device_reset_complete FAILS? */
1560 1541
1561 dev_dbg(&isci_host->pdev->dev, 1542int isci_task_I_T_nexus_reset(struct domain_device *dev)
1562 "%s: cmd %p, isci_dev %p complete.\n", 1543{
1563 __func__, cmd, isci_dev); 1544 struct isci_host *ihost = dev_to_ihost(dev);
1545 int ret = TMF_RESP_FUNC_FAILED, hard_reset = 1;
1546 struct isci_remote_device *idev;
1547 unsigned long flags;
1548
1549 /* XXX mvsas is not protecting against ->lldd_dev_gone(), are we
1550 * being too paranoid, or is mvsas busted?!
1551 */
1552 spin_lock_irqsave(&ihost->scic_lock, flags);
1553 idev = dev->lldd_dev;
1554 if (!idev || !test_bit(IDEV_EH, &idev->flags))
1555 ret = TMF_RESP_FUNC_COMPLETE;
1556 spin_unlock_irqrestore(&ihost->scic_lock, flags);
1557
1558 if (ret == TMF_RESP_FUNC_COMPLETE)
1559 return ret;
1560
1561 if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP))
1562 hard_reset = 0;
1563
1564 return isci_reset_device(dev, hard_reset);
1565}
1566
1567int isci_bus_reset_handler(struct scsi_cmnd *cmd)
1568{
1569 struct domain_device *dev = sdev_to_domain_dev(cmd->device);
1570 int hard_reset = 1;
1571
1572 if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP))
1573 hard_reset = 0;
1564 1574
1565 return TMF_RESP_FUNC_COMPLETE; 1575 return isci_reset_device(dev, hard_reset);
1566} 1576}