aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/scsi_lib.c')
-rw-r--r--drivers/scsi/scsi_lib.c75
1 files changed, 39 insertions, 36 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index b83269689542..112c737884c3 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1274,18 +1274,18 @@ static inline int scsi_dev_queue_ready(struct request_queue *q,
1274/* 1274/*
1275 * scsi_target_queue_ready: checks if there we can send commands to target 1275 * scsi_target_queue_ready: checks if there we can send commands to target
1276 * @sdev: scsi device on starget to check. 1276 * @sdev: scsi device on starget to check.
1277 *
1278 * Called with the host lock held.
1279 */ 1277 */
1280static inline int scsi_target_queue_ready(struct Scsi_Host *shost, 1278static inline int scsi_target_queue_ready(struct Scsi_Host *shost,
1281 struct scsi_device *sdev) 1279 struct scsi_device *sdev)
1282{ 1280{
1283 struct scsi_target *starget = scsi_target(sdev); 1281 struct scsi_target *starget = scsi_target(sdev);
1282 int ret = 0;
1284 1283
1284 spin_lock_irq(shost->host_lock);
1285 if (starget->single_lun) { 1285 if (starget->single_lun) {
1286 if (starget->starget_sdev_user && 1286 if (starget->starget_sdev_user &&
1287 starget->starget_sdev_user != sdev) 1287 starget->starget_sdev_user != sdev)
1288 return 0; 1288 goto out;
1289 starget->starget_sdev_user = sdev; 1289 starget->starget_sdev_user = sdev;
1290 } 1290 }
1291 1291
@@ -1293,57 +1293,66 @@ static inline int scsi_target_queue_ready(struct Scsi_Host *shost,
1293 /* 1293 /*
1294 * unblock after target_blocked iterates to zero 1294 * unblock after target_blocked iterates to zero
1295 */ 1295 */
1296 if (--starget->target_blocked == 0) { 1296 if (--starget->target_blocked != 0)
1297 SCSI_LOG_MLQUEUE(3, starget_printk(KERN_INFO, starget, 1297 goto out;
1298 "unblocking target at zero depth\n")); 1298
1299 } else 1299 SCSI_LOG_MLQUEUE(3, starget_printk(KERN_INFO, starget,
1300 return 0; 1300 "unblocking target at zero depth\n"));
1301 } 1301 }
1302 1302
1303 if (scsi_target_is_busy(starget)) { 1303 if (scsi_target_is_busy(starget)) {
1304 list_move_tail(&sdev->starved_entry, &shost->starved_list); 1304 list_move_tail(&sdev->starved_entry, &shost->starved_list);
1305 return 0; 1305 goto out;
1306 } 1306 }
1307 1307
1308 return 1; 1308 scsi_target(sdev)->target_busy++;
1309 ret = 1;
1310out:
1311 spin_unlock_irq(shost->host_lock);
1312 return ret;
1309} 1313}
1310 1314
1311/* 1315/*
1312 * scsi_host_queue_ready: if we can send requests to shost, return 1 else 1316 * scsi_host_queue_ready: if we can send requests to shost, return 1 else
1313 * return 0. We must end up running the queue again whenever 0 is 1317 * return 0. We must end up running the queue again whenever 0 is
1314 * returned, else IO can hang. 1318 * returned, else IO can hang.
1315 *
1316 * Called with host_lock held.
1317 */ 1319 */
1318static inline int scsi_host_queue_ready(struct request_queue *q, 1320static inline int scsi_host_queue_ready(struct request_queue *q,
1319 struct Scsi_Host *shost, 1321 struct Scsi_Host *shost,
1320 struct scsi_device *sdev) 1322 struct scsi_device *sdev)
1321{ 1323{
1324 int ret = 0;
1325
1326 spin_lock_irq(shost->host_lock);
1327
1322 if (scsi_host_in_recovery(shost)) 1328 if (scsi_host_in_recovery(shost))
1323 return 0; 1329 goto out;
1324 if (shost->host_busy == 0 && shost->host_blocked) { 1330 if (shost->host_busy == 0 && shost->host_blocked) {
1325 /* 1331 /*
1326 * unblock after host_blocked iterates to zero 1332 * unblock after host_blocked iterates to zero
1327 */ 1333 */
1328 if (--shost->host_blocked == 0) { 1334 if (--shost->host_blocked != 0)
1329 SCSI_LOG_MLQUEUE(3, 1335 goto out;
1330 shost_printk(KERN_INFO, shost, 1336
1331 "unblocking host at zero depth\n")); 1337 SCSI_LOG_MLQUEUE(3,
1332 } else { 1338 shost_printk(KERN_INFO, shost,
1333 return 0; 1339 "unblocking host at zero depth\n"));
1334 }
1335 } 1340 }
1336 if (scsi_host_is_busy(shost)) { 1341 if (scsi_host_is_busy(shost)) {
1337 if (list_empty(&sdev->starved_entry)) 1342 if (list_empty(&sdev->starved_entry))
1338 list_add_tail(&sdev->starved_entry, &shost->starved_list); 1343 list_add_tail(&sdev->starved_entry, &shost->starved_list);
1339 return 0; 1344 goto out;
1340 } 1345 }
1341 1346
1342 /* We're OK to process the command, so we can't be starved */ 1347 /* We're OK to process the command, so we can't be starved */
1343 if (!list_empty(&sdev->starved_entry)) 1348 if (!list_empty(&sdev->starved_entry))
1344 list_del_init(&sdev->starved_entry); 1349 list_del_init(&sdev->starved_entry);
1345 1350
1346 return 1; 1351 shost->host_busy++;
1352 ret = 1;
1353out:
1354 spin_unlock_irq(shost->host_lock);
1355 return ret;
1347} 1356}
1348 1357
1349/* 1358/*
@@ -1524,7 +1533,7 @@ static void scsi_request_fn(struct request_queue *q)
1524 blk_start_request(req); 1533 blk_start_request(req);
1525 sdev->device_busy++; 1534 sdev->device_busy++;
1526 1535
1527 spin_unlock(q->queue_lock); 1536 spin_unlock_irq(q->queue_lock);
1528 cmd = req->special; 1537 cmd = req->special;
1529 if (unlikely(cmd == NULL)) { 1538 if (unlikely(cmd == NULL)) {
1530 printk(KERN_CRIT "impossible request in %s.\n" 1539 printk(KERN_CRIT "impossible request in %s.\n"
@@ -1534,7 +1543,6 @@ static void scsi_request_fn(struct request_queue *q)
1534 blk_dump_rq_flags(req, "foo"); 1543 blk_dump_rq_flags(req, "foo");
1535 BUG(); 1544 BUG();
1536 } 1545 }
1537 spin_lock(shost->host_lock);
1538 1546
1539 /* 1547 /*
1540 * We hit this when the driver is using a host wide 1548 * We hit this when the driver is using a host wide
@@ -1545,9 +1553,11 @@ static void scsi_request_fn(struct request_queue *q)
1545 * a run when a tag is freed. 1553 * a run when a tag is freed.
1546 */ 1554 */
1547 if (blk_queue_tagged(q) && !blk_rq_tagged(req)) { 1555 if (blk_queue_tagged(q) && !blk_rq_tagged(req)) {
1556 spin_lock_irq(shost->host_lock);
1548 if (list_empty(&sdev->starved_entry)) 1557 if (list_empty(&sdev->starved_entry))
1549 list_add_tail(&sdev->starved_entry, 1558 list_add_tail(&sdev->starved_entry,
1550 &shost->starved_list); 1559 &shost->starved_list);
1560 spin_unlock_irq(shost->host_lock);
1551 goto not_ready; 1561 goto not_ready;
1552 } 1562 }
1553 1563
@@ -1555,16 +1565,7 @@ static void scsi_request_fn(struct request_queue *q)
1555 goto not_ready; 1565 goto not_ready;
1556 1566
1557 if (!scsi_host_queue_ready(q, shost, sdev)) 1567 if (!scsi_host_queue_ready(q, shost, sdev))
1558 goto not_ready; 1568 goto host_not_ready;
1559
1560 scsi_target(sdev)->target_busy++;
1561 shost->host_busy++;
1562
1563 /*
1564 * XXX(hch): This is rather suboptimal, scsi_dispatch_cmd will
1565 * take the lock again.
1566 */
1567 spin_unlock_irq(shost->host_lock);
1568 1569
1569 /* 1570 /*
1570 * Finally, initialize any error handling parameters, and set up 1571 * Finally, initialize any error handling parameters, and set up
@@ -1587,9 +1588,11 @@ static void scsi_request_fn(struct request_queue *q)
1587 1588
1588 return; 1589 return;
1589 1590
1590 not_ready: 1591 host_not_ready:
1592 spin_lock_irq(shost->host_lock);
1593 scsi_target(sdev)->target_busy--;
1591 spin_unlock_irq(shost->host_lock); 1594 spin_unlock_irq(shost->host_lock);
1592 1595 not_ready:
1593 /* 1596 /*
1594 * lock q, handle tag, requeue req, and decrement device_busy. We 1597 * lock q, handle tag, requeue req, and decrement device_busy. We
1595 * must return with queue_lock held. 1598 * must return with queue_lock held.