[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: James Bottomley <James.Bottomley@SteelEye.com>
This commit is contained in:
committed by
James Bottomley
parent
631e8a1398
commit
a283bd37d0
@@ -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,
|
|||||||
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 {
|
|||||||
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;
|
|||||||
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 {
|
|||||||
*/
|
*/
|
||||||
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
|
||||||
|
Reference in New Issue
Block a user