aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@suse.de>2009-11-05 14:33:12 -0500
committerJames Bottomley <James.Bottomley@suse.de>2009-12-04 13:01:30 -0500
commitd139b9bd0e52dda14fd13412e7096e68b56d0076 (patch)
tree518daa6384ff606ec77dd8fe4714ea2f177d92c4
parent5917290ce9b376866b165d02a5ed88d5ecdb32d0 (diff)
[SCSI] scsi_lib_dma: fix bug with dma maps on nested scsi objects
Some of our virtual SCSI hosts don't have a proper bus parent at the top, which can be a problem for doing DMA on them This patch makes the host device cache a pointer to the physical bus device and provides an extra API for setting it (the normal API picks it up from the parent). This patch also modifies the qla2xxx and lpfc vport logic to use the new DMA host setting API. Acked-By: James Smart <james.smart@emulex.com> Cc: Stable Tree <stable@kernel.org> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
-rw-r--r--drivers/scsi/hosts.c13
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c3
-rw-r--r--drivers/scsi/scsi_lib_dma.c4
-rw-r--r--include/scsi/scsi_host.h16
5 files changed, 30 insertions, 8 deletions
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 5fd2da494d08..28a753d796f3 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -180,14 +180,20 @@ void scsi_remove_host(struct Scsi_Host *shost)
180EXPORT_SYMBOL(scsi_remove_host); 180EXPORT_SYMBOL(scsi_remove_host);
181 181
182/** 182/**
183 * scsi_add_host - add a scsi host 183 * scsi_add_host_with_dma - add a scsi host with dma device
184 * @shost: scsi host pointer to add 184 * @shost: scsi host pointer to add
185 * @dev: a struct device of type scsi class 185 * @dev: a struct device of type scsi class
186 * @dma_dev: dma device for the host
187 *
188 * Note: You rarely need to worry about this unless you're in a
189 * virtualised host environments, so use the simpler scsi_add_host()
190 * function instead.
186 * 191 *
187 * Return value: 192 * Return value:
188 * 0 on success / != 0 for error 193 * 0 on success / != 0 for error
189 **/ 194 **/
190int scsi_add_host(struct Scsi_Host *shost, struct device *dev) 195int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
196 struct device *dma_dev)
191{ 197{
192 struct scsi_host_template *sht = shost->hostt; 198 struct scsi_host_template *sht = shost->hostt;
193 int error = -EINVAL; 199 int error = -EINVAL;
@@ -207,6 +213,7 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
207 213
208 if (!shost->shost_gendev.parent) 214 if (!shost->shost_gendev.parent)
209 shost->shost_gendev.parent = dev ? dev : &platform_bus; 215 shost->shost_gendev.parent = dev ? dev : &platform_bus;
216 shost->dma_dev = dma_dev;
210 217
211 error = device_add(&shost->shost_gendev); 218 error = device_add(&shost->shost_gendev);
212 if (error) 219 if (error)
@@ -262,7 +269,7 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
262 fail: 269 fail:
263 return error; 270 return error;
264} 271}
265EXPORT_SYMBOL(scsi_add_host); 272EXPORT_SYMBOL(scsi_add_host_with_dma);
266 273
267static void scsi_host_dev_release(struct device *dev) 274static void scsi_host_dev_release(struct device *dev)
268{ 275{
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 562d8cee874b..f913f1e93635 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -2408,7 +2408,7 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev)
2408 vport->els_tmofunc.function = lpfc_els_timeout; 2408 vport->els_tmofunc.function = lpfc_els_timeout;
2409 vport->els_tmofunc.data = (unsigned long)vport; 2409 vport->els_tmofunc.data = (unsigned long)vport;
2410 2410
2411 error = scsi_add_host(shost, dev); 2411 error = scsi_add_host_with_dma(shost, dev, &phba->pcidev->dev);
2412 if (error) 2412 if (error)
2413 goto out_put_shost; 2413 goto out_put_shost;
2414 2414
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index fbcb82a2f7f4..21e2bc4d7401 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -1654,7 +1654,8 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
1654 fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN); 1654 fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN);
1655 } 1655 }
1656 1656
1657 if (scsi_add_host(vha->host, &fc_vport->dev)) { 1657 if (scsi_add_host_with_dma(vha->host, &fc_vport->dev,
1658 &ha->pdev->dev)) {
1658 DEBUG15(printk("scsi(%ld): scsi_add_host failure for VP[%d].\n", 1659 DEBUG15(printk("scsi(%ld): scsi_add_host failure for VP[%d].\n",
1659 vha->host_no, vha->vp_idx)); 1660 vha->host_no, vha->vp_idx));
1660 goto vport_create_failed_2; 1661 goto vport_create_failed_2;
diff --git a/drivers/scsi/scsi_lib_dma.c b/drivers/scsi/scsi_lib_dma.c
index ac6855cd2657..dcd128583b89 100644
--- a/drivers/scsi/scsi_lib_dma.c
+++ b/drivers/scsi/scsi_lib_dma.c
@@ -23,7 +23,7 @@ int scsi_dma_map(struct scsi_cmnd *cmd)
23 int nseg = 0; 23 int nseg = 0;
24 24
25 if (scsi_sg_count(cmd)) { 25 if (scsi_sg_count(cmd)) {
26 struct device *dev = cmd->device->host->shost_gendev.parent; 26 struct device *dev = cmd->device->host->dma_dev;
27 27
28 nseg = dma_map_sg(dev, scsi_sglist(cmd), scsi_sg_count(cmd), 28 nseg = dma_map_sg(dev, scsi_sglist(cmd), scsi_sg_count(cmd),
29 cmd->sc_data_direction); 29 cmd->sc_data_direction);
@@ -41,7 +41,7 @@ EXPORT_SYMBOL(scsi_dma_map);
41void scsi_dma_unmap(struct scsi_cmnd *cmd) 41void scsi_dma_unmap(struct scsi_cmnd *cmd)
42{ 42{
43 if (scsi_sg_count(cmd)) { 43 if (scsi_sg_count(cmd)) {
44 struct device *dev = cmd->device->host->shost_gendev.parent; 44 struct device *dev = cmd->device->host->dma_dev;
45 45
46 dma_unmap_sg(dev, scsi_sglist(cmd), scsi_sg_count(cmd), 46 dma_unmap_sg(dev, scsi_sglist(cmd), scsi_sg_count(cmd),
47 cmd->sc_data_direction); 47 cmd->sc_data_direction);
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 603054d8f40c..6ff6bc18e294 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -683,6 +683,12 @@ struct Scsi_Host {
683 void *shost_data; 683 void *shost_data;
684 684
685 /* 685 /*
686 * Points to the physical bus device we'd use to do DMA
687 * Needed just in case we have virtual hosts.
688 */
689 struct device *dma_dev;
690
691 /*
686 * We should ensure that this is aligned, both for better performance 692 * We should ensure that this is aligned, both for better performance
687 * and also because some compilers (m68k) don't automatically force 693 * and also because some compilers (m68k) don't automatically force
688 * alignment to a long boundary. 694 * alignment to a long boundary.
@@ -726,7 +732,9 @@ extern int scsi_queue_work(struct Scsi_Host *, struct work_struct *);
726extern void scsi_flush_work(struct Scsi_Host *); 732extern void scsi_flush_work(struct Scsi_Host *);
727 733
728extern struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *, int); 734extern struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *, int);
729extern int __must_check scsi_add_host(struct Scsi_Host *, struct device *); 735extern int __must_check scsi_add_host_with_dma(struct Scsi_Host *,
736 struct device *,
737 struct device *);
730extern void scsi_scan_host(struct Scsi_Host *); 738extern void scsi_scan_host(struct Scsi_Host *);
731extern void scsi_rescan_device(struct device *); 739extern void scsi_rescan_device(struct device *);
732extern void scsi_remove_host(struct Scsi_Host *); 740extern void scsi_remove_host(struct Scsi_Host *);
@@ -737,6 +745,12 @@ extern const char *scsi_host_state_name(enum scsi_host_state);
737 745
738extern u64 scsi_calculate_bounce_limit(struct Scsi_Host *); 746extern u64 scsi_calculate_bounce_limit(struct Scsi_Host *);
739 747
748static inline int __must_check scsi_add_host(struct Scsi_Host *host,
749 struct device *dev)
750{
751 return scsi_add_host_with_dma(host, dev, dev);
752}
753
740static inline struct device *scsi_get_device(struct Scsi_Host *shost) 754static inline struct device *scsi_get_device(struct Scsi_Host *shost)
741{ 755{
742 return shost->shost_gendev.parent; 756 return shost->shost_gendev.parent;