diff options
-rw-r--r-- | drivers/scsi/scsi_scan.c | 16 | ||||
-rw-r--r-- | drivers/scsi/scsi_transport_fc.c | 19 | ||||
-rw-r--r-- | include/scsi/scsi_transport.h | 8 |
3 files changed, 42 insertions, 1 deletions
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 2d3c4ac475f2..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; |
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 35d1c1e8e345..e6412fce423c 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c | |||
@@ -1022,6 +1022,23 @@ static int fc_rport_match(struct attribute_container *cont, | |||
1022 | return &i->rport_attr_cont.ac == cont; | 1022 | return &i->rport_attr_cont.ac == cont; |
1023 | } | 1023 | } |
1024 | 1024 | ||
1025 | |||
1026 | /* | ||
1027 | * Must be called with shost->host_lock held | ||
1028 | */ | ||
1029 | static struct device *fc_target_parent(struct Scsi_Host *shost, | ||
1030 | int channel, uint id) | ||
1031 | { | ||
1032 | struct fc_rport *rport; | ||
1033 | |||
1034 | list_for_each_entry(rport, &fc_host_rports(shost), peers) | ||
1035 | if ((rport->channel == channel) && | ||
1036 | (rport->scsi_target_id == id)) | ||
1037 | return &rport->dev; | ||
1038 | |||
1039 | return NULL; | ||
1040 | } | ||
1041 | |||
1025 | struct scsi_transport_template * | 1042 | struct scsi_transport_template * |
1026 | fc_attach_transport(struct fc_function_template *ft) | 1043 | fc_attach_transport(struct fc_function_template *ft) |
1027 | { | 1044 | { |
@@ -1057,6 +1074,8 @@ fc_attach_transport(struct fc_function_template *ft) | |||
1057 | 1074 | ||
1058 | /* Transport uses the shost workq for scsi scanning */ | 1075 | /* Transport uses the shost workq for scsi scanning */ |
1059 | i->t.create_work_queue = 1; | 1076 | i->t.create_work_queue = 1; |
1077 | |||
1078 | i->t.target_parent = fc_target_parent; | ||
1060 | 1079 | ||
1061 | /* | 1080 | /* |
1062 | * Setup SCSI Target Attributes. | 1081 | * Setup SCSI Target Attributes. |
diff --git a/include/scsi/scsi_transport.h b/include/scsi/scsi_transport.h index a4f1837a33b1..f6e0bb484c63 100644 --- a/include/scsi/scsi_transport.h +++ b/include/scsi/scsi_transport.h | |||
@@ -29,6 +29,14 @@ struct scsi_transport_template { | |||
29 | struct transport_container target_attrs; | 29 | struct transport_container target_attrs; |
30 | struct transport_container device_attrs; | 30 | struct transport_container device_attrs; |
31 | 31 | ||
32 | /* | ||
33 | * If set, call target_parent prior to allocating a scsi_target, | ||
34 | * so we get the appropriate parent for the target. This function | ||
35 | * is required for transports like FC and iSCSI that do not put the | ||
36 | * scsi_target under scsi_host. | ||
37 | */ | ||
38 | struct device *(*target_parent)(struct Scsi_Host *, int, uint); | ||
39 | |||
32 | /* The size of the specific transport attribute structure (a | 40 | /* The size of the specific transport attribute structure (a |
33 | * space of this size will be left at the end of the | 41 | * space of this size will be left at the end of the |
34 | * scsi_* structure */ | 42 | * scsi_* structure */ |