diff options
Diffstat (limited to 'drivers/scsi/scsi_scan.c')
-rw-r--r-- | drivers/scsi/scsi_scan.c | 51 |
1 files changed, 49 insertions, 2 deletions
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 9fa209097e3b..48edd67982a5 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c | |||
@@ -336,9 +336,23 @@ static struct scsi_target *scsi_alloc_target(struct device *parent, | |||
336 | unsigned long flags; | 336 | unsigned long flags; |
337 | const int size = sizeof(struct scsi_target) | 337 | const int size = sizeof(struct scsi_target) |
338 | + shost->transportt->target_size; | 338 | + shost->transportt->target_size; |
339 | struct scsi_target *starget = kmalloc(size, GFP_ATOMIC); | 339 | struct scsi_target *starget; |
340 | struct scsi_target *found_target; | 340 | struct scsi_target *found_target; |
341 | 341 | ||
342 | /* | ||
343 | * Obtain the real parent from the transport. The transport | ||
344 | * is allowed to fail (no error) if there is nothing at that | ||
345 | * target id. | ||
346 | */ | ||
347 | if (shost->transportt->target_parent) { | ||
348 | spin_lock_irqsave(shost->host_lock, flags); | ||
349 | parent = shost->transportt->target_parent(shost, channel, id); | ||
350 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
351 | if (!parent) | ||
352 | return NULL; | ||
353 | } | ||
354 | |||
355 | starget = kmalloc(size, GFP_KERNEL); | ||
342 | if (!starget) { | 356 | if (!starget) { |
343 | printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__); | 357 | printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__); |
344 | return NULL; | 358 | return NULL; |
@@ -756,7 +770,8 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags) | |||
756 | * register it and tell the rest of the kernel | 770 | * register it and tell the rest of the kernel |
757 | * about it. | 771 | * about it. |
758 | */ | 772 | */ |
759 | scsi_sysfs_add_sdev(sdev); | 773 | if (scsi_sysfs_add_sdev(sdev) != 0) |
774 | return SCSI_SCAN_NO_RESPONSE; | ||
760 | 775 | ||
761 | return SCSI_SCAN_LUN_PRESENT; | 776 | return SCSI_SCAN_LUN_PRESENT; |
762 | } | 777 | } |
@@ -1000,6 +1015,38 @@ static int scsilun_to_int(struct scsi_lun *scsilun) | |||
1000 | } | 1015 | } |
1001 | 1016 | ||
1002 | /** | 1017 | /** |
1018 | * int_to_scsilun: reverts an int into a scsi_lun | ||
1019 | * @int: integer to be reverted | ||
1020 | * @scsilun: struct scsi_lun to be set. | ||
1021 | * | ||
1022 | * Description: | ||
1023 | * Reverts the functionality of the scsilun_to_int, which packed | ||
1024 | * an 8-byte lun value into an int. This routine unpacks the int | ||
1025 | * back into the lun value. | ||
1026 | * Note: the scsilun_to_int() routine does not truly handle all | ||
1027 | * 8bytes of the lun value. This functions restores only as much | ||
1028 | * as was set by the routine. | ||
1029 | * | ||
1030 | * Notes: | ||
1031 | * Given an integer : 0x0b030a04, this function returns a | ||
1032 | * scsi_lun of : struct scsi_lun of: 0a 04 0b 03 00 00 00 00 | ||
1033 | * | ||
1034 | **/ | ||
1035 | void int_to_scsilun(unsigned int lun, struct scsi_lun *scsilun) | ||
1036 | { | ||
1037 | int i; | ||
1038 | |||
1039 | memset(scsilun->scsi_lun, 0, sizeof(scsilun->scsi_lun)); | ||
1040 | |||
1041 | for (i = 0; i < sizeof(lun); i += 2) { | ||
1042 | scsilun->scsi_lun[i] = (lun >> 8) & 0xFF; | ||
1043 | scsilun->scsi_lun[i+1] = lun & 0xFF; | ||
1044 | lun = lun >> 16; | ||
1045 | } | ||
1046 | } | ||
1047 | EXPORT_SYMBOL(int_to_scsilun); | ||
1048 | |||
1049 | /** | ||
1003 | * scsi_report_lun_scan - Scan using SCSI REPORT LUN results | 1050 | * scsi_report_lun_scan - Scan using SCSI REPORT LUN results |
1004 | * @sdevscan: scan the host, channel, and id of this Scsi_Device | 1051 | * @sdevscan: scan the host, channel, and id of this Scsi_Device |
1005 | * | 1052 | * |