Skip to content

Commit d139b9b

Browse files
James BottomleyJames Bottomley
authored andcommitted
[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 <[email protected]> Cc: Stable Tree <[email protected]> Signed-off-by: James Bottomley <[email protected]>
1 parent 5917290 commit d139b9b

File tree

5 files changed

+30
-8
lines changed

5 files changed

+30
-8
lines changed

drivers/scsi/hosts.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -180,14 +180,20 @@ void scsi_remove_host(struct Scsi_Host *shost)
180180
EXPORT_SYMBOL(scsi_remove_host);
181181

182182
/**
183-
* scsi_add_host - add a scsi host
183+
* scsi_add_host_with_dma - add a scsi host with dma device
184184
* @shost: scsi host pointer to add
185185
* @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.
186191
*
187192
* Return value:
188193
* 0 on success / != 0 for error
189194
**/
190-
int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
195+
int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
196+
struct device *dma_dev)
191197
{
192198
struct scsi_host_template *sht = shost->hostt;
193199
int error = -EINVAL;
@@ -207,6 +213,7 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
207213

208214
if (!shost->shost_gendev.parent)
209215
shost->shost_gendev.parent = dev ? dev : &platform_bus;
216+
shost->dma_dev = dma_dev;
210217

211218
error = device_add(&shost->shost_gendev);
212219
if (error)
@@ -262,7 +269,7 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
262269
fail:
263270
return error;
264271
}
265-
EXPORT_SYMBOL(scsi_add_host);
272+
EXPORT_SYMBOL(scsi_add_host_with_dma);
266273

267274
static void scsi_host_dev_release(struct device *dev)
268275
{

drivers/scsi/lpfc/lpfc_init.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2408,7 +2408,7 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev)
24082408
vport->els_tmofunc.function = lpfc_els_timeout;
24092409
vport->els_tmofunc.data = (unsigned long)vport;
24102410

2411-
error = scsi_add_host(shost, dev);
2411+
error = scsi_add_host_with_dma(shost, dev, &phba->pcidev->dev);
24122412
if (error)
24132413
goto out_put_shost;
24142414

drivers/scsi/qla2xxx/qla_attr.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1654,7 +1654,8 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
16541654
fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN);
16551655
}
16561656

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)) {
16581659
DEBUG15(printk("scsi(%ld): scsi_add_host failure for VP[%d].\n",
16591660
vha->host_no, vha->vp_idx));
16601661
goto vport_create_failed_2;

drivers/scsi/scsi_lib_dma.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ int scsi_dma_map(struct scsi_cmnd *cmd)
2323
int nseg = 0;
2424

2525
if (scsi_sg_count(cmd)) {
26-
struct device *dev = cmd->device->host->shost_gendev.parent;
26+
struct device *dev = cmd->device->host->dma_dev;
2727

2828
nseg = dma_map_sg(dev, scsi_sglist(cmd), scsi_sg_count(cmd),
2929
cmd->sc_data_direction);
@@ -41,7 +41,7 @@ EXPORT_SYMBOL(scsi_dma_map);
4141
void scsi_dma_unmap(struct scsi_cmnd *cmd)
4242
{
4343
if (scsi_sg_count(cmd)) {
44-
struct device *dev = cmd->device->host->shost_gendev.parent;
44+
struct device *dev = cmd->device->host->dma_dev;
4545

4646
dma_unmap_sg(dev, scsi_sglist(cmd), scsi_sg_count(cmd),
4747
cmd->sc_data_direction);

include/scsi/scsi_host.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,12 @@ struct Scsi_Host {
682682
*/
683683
void *shost_data;
684684

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+
685691
/*
686692
* We should ensure that this is aligned, both for better performance
687693
* and also because some compilers (m68k) don't automatically force
@@ -726,7 +732,9 @@ extern int scsi_queue_work(struct Scsi_Host *, struct work_struct *);
726732
extern void scsi_flush_work(struct Scsi_Host *);
727733

728734
extern struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *, int);
729-
extern int __must_check scsi_add_host(struct Scsi_Host *, struct device *);
735+
extern int __must_check scsi_add_host_with_dma(struct Scsi_Host *,
736+
struct device *,
737+
struct device *);
730738
extern void scsi_scan_host(struct Scsi_Host *);
731739
extern void scsi_rescan_device(struct device *);
732740
extern void scsi_remove_host(struct Scsi_Host *);
@@ -737,6 +745,12 @@ extern const char *scsi_host_state_name(enum scsi_host_state);
737745

738746
extern u64 scsi_calculate_bounce_limit(struct Scsi_Host *);
739747

748+
static 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+
740754
static inline struct device *scsi_get_device(struct Scsi_Host *shost)
741755
{
742756
return shost->shost_gendev.parent;

0 commit comments

Comments
 (0)