diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2005-08-10 09:36:02 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-08-10 09:36:02 -0700 |
commit | 48d28fd55e7fd349fb16a50244379b4da3a4943c (patch) | |
tree | a6239419973b87c0560de36ab9e11516d45173e8 | |
parent | 86b3786078d63242d3194ffc58ae8dae1d1bbef3 (diff) | |
parent | 5bb8345db8f2aef367e0fddf99a42b7a6029b31f (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6
-rw-r--r-- | drivers/scsi/dpt_i2o.c | 9 | ||||
-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 |
4 files changed, 50 insertions, 2 deletions
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index e2370529c63..7235f94f119 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -907,9 +907,13 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev raptorFlag = TRUE; } - + if (pci_request_regions(pDev, "dpt_i2o")) { + PERROR("dpti: adpt_config_hba: pci request region failed\n"); + return -EINVAL; + } base_addr_virt = ioremap(base_addr0_phys,hba_map0_area_size); if (!base_addr_virt) { + pci_release_regions(pDev); PERROR("dpti: adpt_config_hba: io remap failed\n"); return -EINVAL; } @@ -919,6 +923,7 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev if (!msg_addr_virt) { PERROR("dpti: adpt_config_hba: io remap failed on BAR1\n"); iounmap(base_addr_virt); + pci_release_regions(pDev); return -EINVAL; } } else { @@ -932,6 +937,7 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev iounmap(msg_addr_virt); } iounmap(base_addr_virt); + pci_release_regions(pDev); return -ENOMEM; } memset(pHba, 0, sizeof(adpt_hba)); @@ -1027,6 +1033,7 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba) up(&adpt_configuration_lock); iounmap(pHba->base_addr_virt); + pci_release_regions(pHba->pDev); if(pHba->msg_addr_virt != pHba->base_addr_virt){ iounmap(pHba->msg_addr_virt); } diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 2d3c4ac475f..48edd67982a 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, unsigned long flags; const int size = sizeof(struct scsi_target) + shost->transportt->target_size; - struct scsi_target *starget = kmalloc(size, GFP_ATOMIC); + struct scsi_target *starget; struct scsi_target *found_target; + /* + * Obtain the real parent from the transport. The transport + * is allowed to fail (no error) if there is nothing at that + * target id. + */ + if (shost->transportt->target_parent) { + spin_lock_irqsave(shost->host_lock, flags); + parent = shost->transportt->target_parent(shost, channel, id); + spin_unlock_irqrestore(shost->host_lock, flags); + if (!parent) + return NULL; + } + + starget = kmalloc(size, GFP_KERNEL); if (!starget) { printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__); return NULL; diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 35d1c1e8e34..e6412fce423 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, return &i->rport_attr_cont.ac == cont; } + +/* + * Must be called with shost->host_lock held + */ +static struct device *fc_target_parent(struct Scsi_Host *shost, + int channel, uint id) +{ + struct fc_rport *rport; + + list_for_each_entry(rport, &fc_host_rports(shost), peers) + if ((rport->channel == channel) && + (rport->scsi_target_id == id)) + return &rport->dev; + + return NULL; +} + struct scsi_transport_template * fc_attach_transport(struct fc_function_template *ft) { @@ -1057,6 +1074,8 @@ fc_attach_transport(struct fc_function_template *ft) /* Transport uses the shost workq for scsi scanning */ i->t.create_work_queue = 1; + + i->t.target_parent = fc_target_parent; /* * Setup SCSI Target Attributes. diff --git a/include/scsi/scsi_transport.h b/include/scsi/scsi_transport.h index a4f1837a33b..f6e0bb484c6 100644 --- a/include/scsi/scsi_transport.h +++ b/include/scsi/scsi_transport.h @@ -29,6 +29,14 @@ struct scsi_transport_template { struct transport_container target_attrs; struct transport_container device_attrs; + /* + * If set, call target_parent prior to allocating a scsi_target, + * so we get the appropriate parent for the target. This function + * is required for transports like FC and iSCSI that do not put the + * scsi_target under scsi_host. + */ + struct device *(*target_parent)(struct Scsi_Host *, int, uint); + /* The size of the specific transport attribute structure (a * space of this size will be left at the end of the * scsi_* structure */ |