Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
[linux-2.6-microblaze.git] / drivers / scsi / scsi_scan.c
index 9b73aa5..12f5457 100644 (file)
@@ -215,6 +215,7 @@ static void scsi_unlock_floptical(struct scsi_device *sdev,
 static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
                                           u64 lun, void *hostdata)
 {
+       unsigned int depth;
        struct scsi_device *sdev;
        int display_failure_msg = 1, ret;
        struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
@@ -276,8 +277,25 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
        WARN_ON_ONCE(!blk_get_queue(sdev->request_queue));
        sdev->request_queue->queuedata = sdev;
 
-       scsi_change_queue_depth(sdev, sdev->host->cmd_per_lun ?
-                                       sdev->host->cmd_per_lun : 1);
+       depth = sdev->host->cmd_per_lun ?: 1;
+
+       /*
+        * Use .can_queue as budget map's depth because we have to
+        * support adjusting queue depth from sysfs. Meantime use
+        * default device queue depth to figure out sbitmap shift
+        * since we use this queue depth most of times.
+        */
+       if (sbitmap_init_node(&sdev->budget_map,
+                               scsi_device_max_queue_depth(sdev),
+                               sbitmap_calculate_shift(depth),
+                               GFP_KERNEL, sdev->request_queue->node,
+                               false, true)) {
+               put_device(&starget->dev);
+               kfree(sdev);
+               goto out;
+       }
+
+       scsi_change_queue_depth(sdev, depth);
 
        scsi_sysfs_device_initialize(sdev);
 
@@ -979,6 +997,7 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
                scsi_attach_vpd(sdev);
 
        sdev->max_queue_depth = sdev->queue_depth;
+       WARN_ON_ONCE(sdev->max_queue_depth > sdev->budget_map.depth);
        sdev->sdev_bflags = *bflags;
 
        /*