Commit a283bd37 authored by James Bottomley's avatar James Bottomley Committed by James Bottomley

[SCSI] Add target alloc/destroy callbacks to the host template

This gives the HBA driver notice when a target is created and
destroyed to allow it to manage its own target based allocations
accordingly.

This is a much reduced verson of the original patch sent in by
James.Smart@Emulex.com
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 631e8a13
...@@ -293,6 +293,10 @@ static void scsi_target_dev_release(struct device *dev) ...@@ -293,6 +293,10 @@ static void scsi_target_dev_release(struct device *dev)
{ {
struct device *parent = dev->parent; struct device *parent = dev->parent;
struct scsi_target *starget = to_scsi_target(dev); struct scsi_target *starget = to_scsi_target(dev);
struct Scsi_Host *shost = dev_to_shost(parent);
if (shost->hostt->target_destroy)
shost->hostt->target_destroy(starget);
kfree(starget); kfree(starget);
put_device(parent); put_device(parent);
} }
...@@ -360,9 +364,23 @@ static struct scsi_target *scsi_alloc_target(struct device *parent, ...@@ -360,9 +364,23 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
list_add_tail(&starget->siblings, &shost->__targets); list_add_tail(&starget->siblings, &shost->__targets);
spin_unlock_irqrestore(shost->host_lock, flags); spin_unlock_irqrestore(shost->host_lock, flags);
/* allocate and add */ /* allocate and add */
transport_setup_device(&starget->dev); transport_setup_device(dev);
device_add(&starget->dev); device_add(dev);
transport_add_device(&starget->dev); transport_add_device(dev);
if (shost->hostt->target_alloc) {
int error = shost->hostt->target_alloc(starget);
if(error) {
dev_printk(KERN_ERR, dev, "target allocation failed, error %d\n", error);
/* don't want scsi_target_reap to do the final
* put because it will be under the host lock */
get_device(dev);
scsi_target_reap(starget);
put_device(dev);
return NULL;
}
}
return starget; return starget;
found: found:
......
...@@ -154,7 +154,9 @@ struct scsi_target { ...@@ -154,7 +154,9 @@ struct scsi_target {
unsigned int id; /* target id ... replace unsigned int id; /* target id ... replace
* scsi_device.id eventually */ * scsi_device.id eventually */
unsigned long create:1; /* signal that it needs to be added */ unsigned long create:1; /* signal that it needs to be added */
unsigned long starget_data[0]; void *hostdata; /* available to low-level driver */
unsigned long starget_data[0]; /* for the transport */
/* starget_data must be the last element!!!! */
} __attribute__((aligned(sizeof(unsigned long)))); } __attribute__((aligned(sizeof(unsigned long))));
#define to_scsi_target(d) container_of(d, struct scsi_target, dev) #define to_scsi_target(d) container_of(d, struct scsi_target, dev)
......
...@@ -10,6 +10,7 @@ struct block_device; ...@@ -10,6 +10,7 @@ struct block_device;
struct module; struct module;
struct scsi_cmnd; struct scsi_cmnd;
struct scsi_device; struct scsi_device;
struct scsi_target;
struct Scsi_Host; struct Scsi_Host;
struct scsi_host_cmd_pool; struct scsi_host_cmd_pool;
struct scsi_transport_template; struct scsi_transport_template;
...@@ -227,6 +228,30 @@ struct scsi_host_template { ...@@ -227,6 +228,30 @@ struct scsi_host_template {
*/ */
void (* slave_destroy)(struct scsi_device *); void (* slave_destroy)(struct scsi_device *);
/*
* Before the mid layer attempts to scan for a new device attached
* to a target where no target currently exists, it will call this
* entry in your driver. Should your driver need to allocate any
* structs or perform any other init items in order to send commands
* to a currently unused target, then this is where you can perform
* those allocations.
*
* Return values: 0 on success, non-0 on failure
*
* Status: OPTIONAL
*/
int (* target_alloc)(struct scsi_target *);
/*
* Immediately prior to deallocating the target structure, and
* after all activity to attached scsi devices has ceased, the
* midlayer calls this point so that the driver may deallocate
* and terminate any references to the target.
*
* Status: OPTIONAL
*/
void (* target_destroy)(struct scsi_target *);
/* /*
* fill in this function to allow the queue depth of this host * fill in this function to allow the queue depth of this host
* to be changeable (on a per device basis). returns either * to be changeable (on a per device basis). returns either
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment