Commit d0a7e574007fd547d72ec693bfa35778623d0738

Authored by James Bottomley
Committed by James Bottomley
1 parent 10c1b88987

[SCSI] correct transport class abstraction to work outside SCSI

I recently tried to construct a totally generic transport class and
found there were certain features missing from the current abstract
transport class.  Most notable is that you have to hang the data on the
class_device but most of the API is framed in terms of the generic
device, not the class_device.

These changes are two fold

- Provide the class_device to all of the setup and configure APIs
- Provide and extra API to take the device and the attribute class and
  return the corresponding class_device

Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>

Showing 6 changed files with 72 additions and 20 deletions Side-by-side Diff

drivers/base/attribute_container.c
... ... @@ -58,6 +58,7 @@
58 58 {
59 59 INIT_LIST_HEAD(&cont->node);
60 60 INIT_LIST_HEAD(&cont->containers);
  61 + spin_lock_init(&cont->containers_lock);
61 62  
62 63 down(&attribute_container_mutex);
63 64 list_add_tail(&cont->node, &attribute_container_list);
64 65  
... ... @@ -77,11 +78,13 @@
77 78 {
78 79 int retval = -EBUSY;
79 80 down(&attribute_container_mutex);
  81 + spin_lock(&cont->containers_lock);
80 82 if (!list_empty(&cont->containers))
81 83 goto out;
82 84 retval = 0;
83 85 list_del(&cont->node);
84 86 out:
  87 + spin_unlock(&cont->containers_lock);
85 88 up(&attribute_container_mutex);
86 89 return retval;
87 90  
88 91  
... ... @@ -151,7 +154,9 @@
151 154 fn(cont, dev, &ic->classdev);
152 155 else
153 156 attribute_container_add_class_device(&ic->classdev);
  157 + spin_lock(&cont->containers_lock);
154 158 list_add_tail(&ic->node, &cont->containers);
  159 + spin_unlock(&cont->containers_lock);
155 160 }
156 161 up(&attribute_container_mutex);
157 162 }
... ... @@ -189,6 +194,7 @@
189 194  
190 195 if (!cont->match(cont, dev))
191 196 continue;
  197 + spin_lock(&cont->containers_lock);
192 198 list_for_each_entry_safe(ic, tmp, &cont->containers, node) {
193 199 if (dev != ic->classdev.dev)
194 200 continue;
... ... @@ -200,6 +206,7 @@
200 206 class_device_unregister(&ic->classdev);
201 207 }
202 208 }
  209 + spin_unlock(&cont->containers_lock);
203 210 }
204 211 up(&attribute_container_mutex);
205 212 }
206 213  
... ... @@ -230,10 +237,12 @@
230 237 if (!cont->match(cont, dev))
231 238 continue;
232 239  
  240 + spin_lock(&cont->containers_lock);
233 241 list_for_each_entry_safe(ic, tmp, &cont->containers, node) {
234 242 if (dev == ic->classdev.dev)
235 243 fn(cont, dev, &ic->classdev);
236 244 }
  245 + spin_unlock(&cont->containers_lock);
237 246 }
238 247 up(&attribute_container_mutex);
239 248 }
... ... @@ -367,6 +376,35 @@
367 376 class_device_del(classdev);
368 377 }
369 378 EXPORT_SYMBOL_GPL(attribute_container_class_device_del);
  379 +
  380 +/**
  381 + * attribute_container_find_class_device - find the corresponding class_device
  382 + *
  383 + * @cont: the container
  384 + * @dev: the generic device
  385 + *
  386 + * Looks up the device in the container's list of class devices and returns
  387 + * the corresponding class_device.
  388 + */
  389 +struct class_device *
  390 +attribute_container_find_class_device(struct attribute_container *cont,
  391 + struct device *dev)
  392 +{
  393 + struct class_device *cdev = NULL;
  394 + struct internal_container *ic;
  395 +
  396 + spin_lock(&cont->containers_lock);
  397 + list_for_each_entry(ic, &cont->containers, node) {
  398 + if (ic->classdev.dev == dev) {
  399 + cdev = &ic->classdev;
  400 + break;
  401 + }
  402 + }
  403 + spin_unlock(&cont->containers_lock);
  404 +
  405 + return cdev;
  406 +}
  407 +EXPORT_SYMBOL_GPL(attribute_container_find_class_device);
370 408  
371 409 int __init
372 410 attribute_container_init(void)
drivers/base/transport_class.c
... ... @@ -64,7 +64,9 @@
64 64 }
65 65 EXPORT_SYMBOL_GPL(transport_class_unregister);
66 66  
67   -static int anon_transport_dummy_function(struct device *dev)
  67 +static int anon_transport_dummy_function(struct transport_container *tc,
  68 + struct device *dev,
  69 + struct class_device *cdev)
68 70 {
69 71 /* do nothing */
70 72 return 0;
71 73  
... ... @@ -115,9 +117,10 @@
115 117 struct class_device *classdev)
116 118 {
117 119 struct transport_class *tclass = class_to_transport_class(cont->class);
  120 + struct transport_container *tcont = attribute_container_to_transport_container(cont);
118 121  
119 122 if (tclass->setup)
120   - tclass->setup(dev);
  123 + tclass->setup(tcont, dev, classdev);
121 124  
122 125 return 0;
123 126 }
124 127  
125 128  
... ... @@ -178,12 +181,14 @@
178 181 EXPORT_SYMBOL_GPL(transport_add_device);
179 182  
180 183 static int transport_configure(struct attribute_container *cont,
181   - struct device *dev)
  184 + struct device *dev,
  185 + struct class_device *cdev)
182 186 {
183 187 struct transport_class *tclass = class_to_transport_class(cont->class);
  188 + struct transport_container *tcont = attribute_container_to_transport_container(cont);
184 189  
185 190 if (tclass->configure)
186   - tclass->configure(dev);
  191 + tclass->configure(tcont, dev, cdev);
187 192  
188 193 return 0;
189 194 }
... ... @@ -202,7 +207,7 @@
202 207 */
203 208 void transport_configure_device(struct device *dev)
204 209 {
205   - attribute_container_trigger(dev, transport_configure);
  210 + attribute_container_device_trigger(dev, transport_configure);
206 211 }
207 212 EXPORT_SYMBOL_GPL(transport_configure_device);
208 213  
... ... @@ -215,7 +220,7 @@
215 220 struct transport_class *tclass = class_to_transport_class(cont->class);
216 221  
217 222 if (tclass->remove)
218   - tclass->remove(dev);
  223 + tclass->remove(tcont, dev, classdev);
219 224  
220 225 if (tclass->remove != anon_transport_dummy_function) {
221 226 if (tcont->statistics)
drivers/scsi/scsi_transport_fc.c
... ... @@ -252,7 +252,8 @@
252 252  
253 253 #define to_fc_internal(tmpl) container_of(tmpl, struct fc_internal, t)
254 254  
255   -static int fc_target_setup(struct device *dev)
  255 +static int fc_target_setup(struct transport_container *tc, struct device *dev,
  256 + struct class_device *cdev)
256 257 {
257 258 struct scsi_target *starget = to_scsi_target(dev);
258 259 struct fc_rport *rport = starget_to_rport(starget);
... ... @@ -281,7 +282,8 @@
281 282 NULL,
282 283 NULL);
283 284  
284   -static int fc_host_setup(struct device *dev)
  285 +static int fc_host_setup(struct transport_container *tc, struct device *dev,
  286 + struct class_device *cdev)
285 287 {
286 288 struct Scsi_Host *shost = dev_to_shost(dev);
287 289  
drivers/scsi/scsi_transport_spi.c
... ... @@ -162,7 +162,8 @@
162 162 return SPI_SIGNAL_UNKNOWN;
163 163 }
164 164  
165   -static int spi_host_setup(struct device *dev)
  165 +static int spi_host_setup(struct transport_container *tc, struct device *dev,
  166 + struct class_device *cdev)
166 167 {
167 168 struct Scsi_Host *shost = dev_to_shost(dev);
168 169  
... ... @@ -196,7 +197,9 @@
196 197 return &i->t.host_attrs.ac == cont;
197 198 }
198 199  
199   -static int spi_device_configure(struct device *dev)
  200 +static int spi_device_configure(struct transport_container *tc,
  201 + struct device *dev,
  202 + struct class_device *cdev)
200 203 {
201 204 struct scsi_device *sdev = to_scsi_device(dev);
202 205 struct scsi_target *starget = sdev->sdev_target;
... ... @@ -214,7 +217,9 @@
214 217 return 0;
215 218 }
216 219  
217   -static int spi_setup_transport_attrs(struct device *dev)
  220 +static int spi_setup_transport_attrs(struct transport_container *tc,
  221 + struct device *dev,
  222 + struct class_device *cdev)
218 223 {
219 224 struct scsi_target *starget = to_scsi_target(dev);
220 225  
include/linux/attribute_container.h
... ... @@ -11,10 +11,12 @@
11 11  
12 12 #include <linux/device.h>
13 13 #include <linux/list.h>
  14 +#include <linux/spinlock.h>
14 15  
15 16 struct attribute_container {
16 17 struct list_head node;
17 18 struct list_head containers;
  19 + spinlock_t containers_lock;
18 20 struct class *class;
19 21 struct class_device_attribute **attrs;
20 22 int (*match)(struct attribute_container *, struct device *);
... ... @@ -62,12 +64,7 @@
62 64 struct class_device *classdev);
63 65 void attribute_container_remove_attrs(struct class_device *classdev);
64 66 void attribute_container_class_device_del(struct class_device *classdev);
65   -
66   -
67   -
68   -
69   -
70   -
  67 +struct class_device *attribute_container_find_class_device(struct attribute_container *, struct device *);
71 68 struct class_device_attribute **attribute_container_classdev_to_attrs(const struct class_device *classdev);
72 69  
73 70 #endif
include/linux/transport_class.h
... ... @@ -12,11 +12,16 @@
12 12 #include <linux/device.h>
13 13 #include <linux/attribute_container.h>
14 14  
  15 +struct transport_container;
  16 +
15 17 struct transport_class {
16 18 struct class class;
17   - int (*setup)(struct device *);
18   - int (*configure)(struct device *);
19   - int (*remove)(struct device *);
  19 + int (*setup)(struct transport_container *, struct device *,
  20 + struct class_device *);
  21 + int (*configure)(struct transport_container *, struct device *,
  22 + struct class_device *);
  23 + int (*remove)(struct transport_container *, struct device *,
  24 + struct class_device *);
20 25 };
21 26  
22 27 #define DECLARE_TRANSPORT_CLASS(cls, nm, su, rm, cfg) \