]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.25/patches.fixes/scsi-skip-nonscsi-device-for-dma
Updated xen patches taken from suse.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.fixes / scsi-skip-nonscsi-device-for-dma
1 From: James Smart <james.smart@emulex.com>
2 Subject: scsi_lib_dma.c : fix bug w/ dma on virtual fc ports
3 References: bnc#431294
4
5 When the updated scsi dma code was introduced recently, it assumed
6 the physical host/adapter was the parent of the scsi host.
7 Unfortunately, on FC virtual ports, the parent of the scsi host is
8 the virtual port, which does not have dma information.
9
10 I have updated the dma routines to use a function that finds the
11 first non-scsi object. A non-scsi object is defined to be an object
12 that has a non-NULL type (assumes all transport objects have NULL
13 types) or a non-scsi_host type.
14
15 -- james s
16
17 Unfortunately the original patch is not correct, as eg the PCI device
18 doesn't set the 'type' pointer, so the system will crash miserably.
19 We should rather check for the 'bus' argument, and return the original
20 argument if we don't find anything.
21
22 Signed-off-by: Hannes Reinecke <hare@suse.de>
23
24 diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
25 index 69321e3..208e7df 100644
26 --- a/drivers/scsi/scsi_lib.c
27 +++ b/drivers/scsi/scsi_lib.c
28 @@ -1713,7 +1713,7 @@ struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost,
29 request_fn_proc *request_fn)
30 {
31 struct request_queue *q;
32 - struct device *dev = shost->shost_gendev.parent;
33 + struct device *dev = dev_to_nonscsi_dev(shost->shost_gendev.parent);
34
35 q = blk_init_queue(request_fn, NULL);
36 if (!q)
37 diff --git a/drivers/scsi/scsi_lib_dma.c b/drivers/scsi/scsi_lib_dma.c
38 index ac6855c..567cdbc 100644
39 --- a/drivers/scsi/scsi_lib_dma.c
40 +++ b/drivers/scsi/scsi_lib_dma.c
41 @@ -23,7 +23,8 @@ int scsi_dma_map(struct scsi_cmnd *cmd)
42 int nseg = 0;
43
44 if (scsi_sg_count(cmd)) {
45 - struct device *dev = cmd->device->host->shost_gendev.parent;
46 + struct device *dev = dev_to_nonscsi_dev(
47 + cmd->device->host->shost_gendev.parent);
48
49 nseg = dma_map_sg(dev, scsi_sglist(cmd), scsi_sg_count(cmd),
50 cmd->sc_data_direction);
51 @@ -41,10 +42,12 @@ EXPORT_SYMBOL(scsi_dma_map);
52 void scsi_dma_unmap(struct scsi_cmnd *cmd)
53 {
54 if (scsi_sg_count(cmd)) {
55 - struct device *dev = cmd->device->host->shost_gendev.parent;
56 + struct device *dev = dev_to_nonscsi_dev(
57 + cmd->device->host->shost_gendev.parent);
58
59 dma_unmap_sg(dev, scsi_sglist(cmd), scsi_sg_count(cmd),
60 cmd->sc_data_direction);
61 }
62 }
63 EXPORT_SYMBOL(scsi_dma_unmap);
64 +
65 diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
66 index d123ca8..55d74c8 100644
67 --- a/include/scsi/scsi_host.h
68 +++ b/include/scsi/scsi_host.h
69 @@ -689,6 +689,10 @@ static inline void *shost_priv(struct Scsi_Host *shost)
70
71 int scsi_is_host_device(const struct device *);
72
73 +/*
74 + * walks object list backward, to find the first shost object.
75 + * Skips over transport objects that may not be stargets, etc
76 + */
77 static inline struct Scsi_Host *dev_to_shost(struct device *dev)
78 {
79 while (!scsi_is_host_device(dev)) {
80 @@ -699,6 +703,26 @@ static inline struct Scsi_Host *dev_to_shost(struct device *dev)
81 return container_of(dev, struct Scsi_Host, shost_gendev);
82 }
83
84 +/*
85 + * walks object list backward, to find the first physical
86 + * device object. If none is found return the original device.
87 + */
88 +static inline struct device *dev_to_nonscsi_dev(struct device *dev)
89 +{
90 + struct device *orig = dev;
91 +
92 + while (dev && (dev->bus == NULL || scsi_is_host_device(dev))) {
93 + if (dev->dma_parms) {
94 + dev_printk(KERN_WARNING, dev,
95 + "dma_parms set, bus %p\n",
96 + dev->bus);
97 + break;
98 + }
99 + dev = dev->parent;
100 + }
101 + return dev?dev:orig;
102 +}
103 +
104 static inline int scsi_host_in_recovery(struct Scsi_Host *shost)
105 {
106 return shost->shost_state == SHOST_RECOVERY ||