aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/isci/remote_device.c
diff options
context:
space:
mode:
authorJeff Skirvin <jeffrey.d.skirvin@intel.com>2012-03-09 01:41:51 -0500
committerDan Williams <dan.j.williams@intel.com>2012-05-17 17:33:37 -0400
commit5b6bf225e7fc249c703e19bf2c983d1a59178874 (patch)
tree9c9b855474b77323c0d89b33ac224e0c1f016c73 /drivers/scsi/isci/remote_device.c
parent726980d56908f2e230624394f03743689db3110c (diff)
isci: Manage device suspensions during TC terminations.
TCs must be terminated only while the RNC is suspended. This commit adds remote device suspensions and resumptions in the abort, reset and termination paths. Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/scsi/isci/remote_device.c')
-rw-r--r--drivers/scsi/isci/remote_device.c90
1 files changed, 73 insertions, 17 deletions
diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c
index 9f03877534d..4f76dcd1cec 100644
--- a/drivers/scsi/isci/remote_device.c
+++ b/drivers/scsi/isci/remote_device.c
@@ -143,6 +143,12 @@ static enum sci_status sci_remote_device_suspend(
143 NULL, NULL); 143 NULL, NULL);
144} 144}
145 145
146static int isci_remote_device_suspendcheck(struct isci_remote_device *idev)
147{
148 return test_bit(IDEV_TXRX_SUSPENDED, &idev->flags)
149 || !test_bit(IDEV_ALLOCATED, &idev->flags);
150}
151
146enum sci_status isci_remote_device_suspend( 152enum sci_status isci_remote_device_suspend(
147 struct isci_host *ihost, 153 struct isci_host *ihost,
148 struct isci_remote_device *idev) 154 struct isci_remote_device *idev)
@@ -151,18 +157,18 @@ enum sci_status isci_remote_device_suspend(
151 unsigned long flags; 157 unsigned long flags;
152 158
153 spin_lock_irqsave(&ihost->scic_lock, flags); 159 spin_lock_irqsave(&ihost->scic_lock, flags);
154 160 if (isci_get_device(idev->domain_dev) == NULL) {
155 if (isci_lookup_device(idev->domain_dev) == NULL) {
156 spin_unlock_irqrestore(&ihost->scic_lock, flags); 161 spin_unlock_irqrestore(&ihost->scic_lock, flags);
157 status = SCI_FAILURE; 162 status = SCI_FAILURE;
158 } else { 163 } else {
159 status = sci_remote_device_suspend(idev); 164 status = sci_remote_device_suspend(idev);
160 spin_unlock_irqrestore(&ihost->scic_lock, flags); 165 spin_unlock_irqrestore(&ihost->scic_lock, flags);
161 if (status == SCI_SUCCESS) { 166 if (status == SCI_SUCCESS) {
167 dev_dbg(&ihost->pdev->dev,
168 "%s: idev=%p, about to wait\n",
169 __func__, idev);
162 wait_event(ihost->eventq, 170 wait_event(ihost->eventq,
163 test_bit(IDEV_TXRX_SUSPENDED, &idev->flags) 171 isci_remote_device_suspendcheck(idev));
164 || !test_bit(IDEV_ALLOCATED, &idev->flags));
165
166 status = test_bit(IDEV_TXRX_SUSPENDED, &idev->flags) 172 status = test_bit(IDEV_TXRX_SUSPENDED, &idev->flags)
167 ? SCI_SUCCESS : SCI_FAILURE; 173 ? SCI_SUCCESS : SCI_FAILURE;
168 dev_dbg(&ihost->pdev->dev, 174 dev_dbg(&ihost->pdev->dev,
@@ -171,7 +177,10 @@ enum sci_status isci_remote_device_suspend(
171 test_bit(IDEV_TXRX_SUSPENDED, &idev->flags) 177 test_bit(IDEV_TXRX_SUSPENDED, &idev->flags)
172 ? "<suspended>" : "<deallocated!>"); 178 ? "<suspended>" : "<deallocated!>");
173 179
174 } 180 } else
181 dev_dbg(scirdev_to_dev(idev),
182 "%s: sci_remote_device_suspend failed, "
183 "status = %d\n", __func__, status);
175 isci_put_device(idev); 184 isci_put_device(idev);
176 } 185 }
177 return status; 186 return status;
@@ -1218,6 +1227,35 @@ static enum sci_status sci_remote_device_ea_construct(struct isci_port *iport,
1218 return SCI_SUCCESS; 1227 return SCI_SUCCESS;
1219} 1228}
1220 1229
1230enum sci_status sci_remote_device_resume(
1231 struct isci_remote_device *idev,
1232 scics_sds_remote_node_context_callback cb_fn,
1233 void *cb_p)
1234{
1235 enum sci_status status;
1236
1237 status = sci_remote_node_context_resume(&idev->rnc, cb_fn, cb_p);
1238 if (status != SCI_SUCCESS)
1239 dev_dbg(scirdev_to_dev(idev), "%s: failed to resume: %d\n",
1240 __func__, status);
1241 return status;
1242}
1243
1244enum sci_status isci_remote_device_resume(
1245 struct isci_host *ihost,
1246 struct isci_remote_device *idev,
1247 scics_sds_remote_node_context_callback cb_fn,
1248 void *cb_p)
1249{
1250 unsigned long flags;
1251 enum sci_status status;
1252
1253 spin_lock_irqsave(&ihost->scic_lock, flags);
1254 status = sci_remote_device_resume(idev, cb_fn, cb_p);
1255 spin_unlock_irqrestore(&ihost->scic_lock, flags);
1256
1257 return status;
1258}
1221/** 1259/**
1222 * sci_remote_device_start() - This method will start the supplied remote 1260 * sci_remote_device_start() - This method will start the supplied remote
1223 * device. This method enables normal IO requests to flow through to the 1261 * device. This method enables normal IO requests to flow through to the
@@ -1244,9 +1282,8 @@ static enum sci_status sci_remote_device_start(struct isci_remote_device *idev,
1244 return SCI_FAILURE_INVALID_STATE; 1282 return SCI_FAILURE_INVALID_STATE;
1245 } 1283 }
1246 1284
1247 status = sci_remote_node_context_resume(&idev->rnc, 1285 status = sci_remote_device_resume(idev, remote_device_resume_done,
1248 remote_device_resume_done, 1286 idev);
1249 idev);
1250 if (status != SCI_SUCCESS) 1287 if (status != SCI_SUCCESS)
1251 return status; 1288 return status;
1252 1289
@@ -1461,26 +1498,29 @@ int isci_remote_device_found(struct domain_device *dev)
1461} 1498}
1462 1499
1463enum sci_status isci_remote_device_reset( 1500enum sci_status isci_remote_device_reset(
1501 struct isci_host *ihost,
1464 struct isci_remote_device *idev) 1502 struct isci_remote_device *idev)
1465{ 1503{
1466 struct isci_host *ihost = dev_to_ihost(idev->domain_dev);
1467 unsigned long flags; 1504 unsigned long flags;
1468 enum sci_status status; 1505 enum sci_status status;
1469 1506
1470 /* Wait for the device suspend. */ 1507 /* Put the device into a reset state so the suspension will not
1471 status = isci_remote_device_suspend(ihost, idev); 1508 * automatically resume.
1509 */
1510 spin_lock_irqsave(&ihost->scic_lock, flags);
1511 status = sci_remote_device_reset(idev);
1512 spin_unlock_irqrestore(&ihost->scic_lock, flags);
1472 if (status != SCI_SUCCESS) { 1513 if (status != SCI_SUCCESS) {
1473 dev_dbg(&ihost->pdev->dev, 1514 dev_dbg(&ihost->pdev->dev,
1474 "%s: isci_remote_device_suspend(%p) returned %d!\n", 1515 "%s: sci_remote_device_reset(%p) returned %d!\n",
1475 __func__, idev, status); 1516 __func__, idev, status);
1476 return status; 1517 return status;
1477 } 1518 }
1478 spin_lock_irqsave(&ihost->scic_lock, flags); 1519 /* Wait for the device suspend. */
1479 status = sci_remote_device_reset(idev); 1520 status = isci_remote_device_suspend(ihost, idev);
1480 spin_unlock_irqrestore(&ihost->scic_lock, flags);
1481 if (status != SCI_SUCCESS) { 1521 if (status != SCI_SUCCESS) {
1482 dev_dbg(&ihost->pdev->dev, 1522 dev_dbg(&ihost->pdev->dev,
1483 "%s: sci_remote_device_reset(%p) returned %d!\n", 1523 "%s: isci_remote_device_suspend(%p) returned %d!\n",
1484 __func__, idev, status); 1524 __func__, idev, status);
1485 } 1525 }
1486 return status; 1526 return status;
@@ -1497,3 +1537,19 @@ enum sci_status sci_remote_device_abort_requests_pending_abort(
1497{ 1537{
1498 return sci_remote_device_terminate_requests_checkabort(idev, 1); 1538 return sci_remote_device_terminate_requests_checkabort(idev, 1);
1499} 1539}
1540
1541enum sci_status isci_remote_device_reset_complete(
1542 struct isci_host *ihost,
1543 struct isci_remote_device *idev)
1544{
1545 unsigned long flags;
1546 enum sci_status status;
1547
1548 spin_lock_irqsave(&ihost->scic_lock, flags);
1549 status = sci_remote_device_reset_complete(idev);
1550 sci_remote_device_resume(idev, NULL, NULL);
1551 spin_unlock_irqrestore(&ihost->scic_lock, flags);
1552
1553 return status;
1554}
1555