spin_unlock_irqrestore(shost->host_lock, flags);
        }
 
-       spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
-       sdev->device_busy--;
-       spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
+       atomic_dec(&sdev->device_busy);
 }
 
 /*
 
 static inline int scsi_device_is_busy(struct scsi_device *sdev)
 {
-       if (sdev->device_busy >= sdev->queue_depth || sdev->device_blocked)
+       if (atomic_read(&sdev->device_busy) >= sdev->queue_depth ||
+           sdev->device_blocked)
                return 1;
-
        return 0;
 }
 
                 * queue must be restarted, so we schedule a callback to happen
                 * shortly.
                 */
-               if (sdev->device_busy == 0)
+               if (atomic_read(&sdev->device_busy) == 0)
                        blk_delay_queue(q, SCSI_QUEUE_DELAY);
                break;
        default:
 static inline int scsi_dev_queue_ready(struct request_queue *q,
                                  struct scsi_device *sdev)
 {
-       if (sdev->device_busy == 0 && sdev->device_blocked) {
+       unsigned int busy;
+
+       busy = atomic_inc_return(&sdev->device_busy) - 1;
+       if (sdev->device_blocked) {
+               if (busy)
+                       goto out_dec;
+
                /*
                 * unblock after device_blocked iterates to zero
                 */
-               if (--sdev->device_blocked == 0) {
-                       SCSI_LOG_MLQUEUE(3,
-                                  sdev_printk(KERN_INFO, sdev,
-                                  "unblocking device at zero depth\n"));
-               } else {
+               if (--sdev->device_blocked != 0) {
                        blk_delay_queue(q, SCSI_QUEUE_DELAY);
-                       return 0;
+                       goto out_dec;
                }
+               SCSI_LOG_MLQUEUE(3, sdev_printk(KERN_INFO, sdev,
+                                  "unblocking device at zero depth\n"));
        }
-       if (scsi_device_is_busy(sdev))
-               return 0;
+
+       if (busy >= sdev->queue_depth)
+               goto out_dec;
 
        return 1;
+out_dec:
+       atomic_dec(&sdev->device_busy);
+       return 0;
 }
 
-
 /*
  * scsi_target_queue_ready: checks if there we can send commands to target
  * @sdev: scsi device on starget to check.
         * bump busy counts.  To bump the counters, we need to dance
         * with the locks as normal issue path does.
         */
-       sdev->device_busy++;
+       atomic_inc(&sdev->device_busy);
        atomic_inc(&shost->host_busy);
        atomic_inc(&starget->target_busy);
 
                 * accept it.
                 */
                req = blk_peek_request(q);
-               if (!req || !scsi_dev_queue_ready(q, sdev))
+               if (!req)
                        break;
 
                if (unlikely(!scsi_device_online(sdev))) {
                        continue;
                }
 
+               if (!scsi_dev_queue_ready(q, sdev))
+                       break;
 
                /*
                 * Remove the request from the request list.
                 */
                if (!(blk_queue_tagged(q) && !blk_queue_start_tag(q, req)))
                        blk_start_request(req);
-               sdev->device_busy++;
 
                spin_unlock_irq(q->queue_lock);
                cmd = req->special;
         */
        spin_lock_irq(q->queue_lock);
        blk_requeue_request(q, req);
-       sdev->device_busy--;
+       atomic_dec(&sdev->device_busy);
 out_delay:
-       if (sdev->device_busy == 0 && !scsi_device_blocked(sdev))
+       if (atomic_read(&sdev->device_busy) && !scsi_device_blocked(sdev))
                blk_delay_queue(q, SCSI_QUEUE_DELAY);
 }
 
                return err;
 
        scsi_run_queue(sdev->request_queue);
-       while (sdev->device_busy) {
+       while (atomic_read(&sdev->device_busy)) {
                msleep_interruptible(200);
                scsi_run_queue(sdev->request_queue);
        }
 
  * Create the actual show/store functions and data structures.
  */
 sdev_rd_attr (device_blocked, "%d\n");
-sdev_rd_attr (device_busy, "%d\n");
 sdev_rd_attr (type, "%d\n");
 sdev_rd_attr (scsi_level, "%d\n");
 sdev_rd_attr (vendor, "%.8s\n");
 sdev_rd_attr (model, "%.16s\n");
 sdev_rd_attr (rev, "%.4s\n");
 
+static ssize_t
+sdev_show_device_busy(struct device *dev, struct device_attribute *attr,
+               char *buf)
+{
+       struct scsi_device *sdev = to_scsi_device(dev);
+       return snprintf(buf, 20, "%d\n", atomic_read(&sdev->device_busy));
+}
+static DEVICE_ATTR(device_busy, S_IRUGO, sdev_show_device_busy, NULL);
+
 /*
  * TODO: can we make these symlinks to the block layer ones?
  */