aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@steeleye.com>2005-08-14 18:09:01 -0400
committerJames Bottomley <jejb@mulgrave.(none)>2005-08-14 18:21:27 -0400
commitd0a7e574007fd547d72ec693bfa35778623d0738 (patch)
tree3457bdf4e8eaf870971aab03c99c31534ba85658
parent10c1b88987d618f4f89c10e11e574c76de73b5e7 (diff)
[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>
-rw-r--r--drivers/base/attribute_container.c38
-rw-r--r--drivers/base/transport_class.c17
-rw-r--r--drivers/scsi/scsi_transport_fc.c6
-rw-r--r--drivers/scsi/scsi_transport_spi.c11
-rw-r--r--include/linux/attribute_container.h9
-rw-r--r--include/linux/transport_class.h11
6 files changed, 72 insertions, 20 deletions
diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c
index ec615d854be9..62c093db11e6 100644
--- a/drivers/base/attribute_container.c
+++ b/drivers/base/attribute_container.c
@@ -58,6 +58,7 @@ attribute_container_register(struct attribute_container *cont)
58{ 58{
59 INIT_LIST_HEAD(&cont->node); 59 INIT_LIST_HEAD(&cont->node);
60 INIT_LIST_HEAD(&cont->containers); 60 INIT_LIST_HEAD(&cont->containers);
61 spin_lock_init(&cont->containers_lock);
61 62
62 down(&attribute_container_mutex); 63 down(&attribute_container_mutex);
63 list_add_tail(&cont->node, &attribute_container_list); 64 list_add_tail(&cont->node, &attribute_container_list);
@@ -77,11 +78,13 @@ attribute_container_unregister(struct attribute_container *cont)
77{ 78{
78 int retval = -EBUSY; 79 int retval = -EBUSY;
79 down(&attribute_container_mutex); 80 down(&attribute_container_mutex);
81 spin_lock(&cont->containers_lock);
80 if (!list_empty(&cont->containers)) 82 if (!list_empty(&cont->containers))
81 goto out; 83 goto out;
82 retval = 0; 84 retval = 0;
83 list_del(&cont->node); 85 list_del(&cont->node);
84 out: 86 out:
87 spin_unlock(&cont->containers_lock);
85 up(&attribute_container_mutex); 88 up(&attribute_container_mutex);
86 return retval; 89 return retval;
87 90
@@ -151,7 +154,9 @@ attribute_container_add_device(struct device *dev,
151 fn(cont, dev, &ic->classdev); 154 fn(cont, dev, &ic->classdev);
152 else 155 else
153 attribute_container_add_class_device(&ic->classdev); 156 attribute_container_add_class_device(&ic->classdev);
157 spin_lock(&cont->containers_lock);
154 list_add_tail(&ic->node, &cont->containers); 158 list_add_tail(&ic->node, &cont->containers);
159 spin_unlock(&cont->containers_lock);
155 } 160 }
156 up(&attribute_container_mutex); 161 up(&attribute_container_mutex);
157} 162}
@@ -189,6 +194,7 @@ attribute_container_remove_device(struct device *dev,
189 194
190 if (!cont->match(cont, dev)) 195 if (!cont->match(cont, dev))
191 continue; 196 continue;
197 spin_lock(&cont->containers_lock);
192 list_for_each_entry_safe(ic, tmp, &cont->containers, node) { 198 list_for_each_entry_safe(ic, tmp, &cont->containers, node) {
193 if (dev != ic->classdev.dev) 199 if (dev != ic->classdev.dev)
194 continue; 200 continue;
@@ -200,6 +206,7 @@ attribute_container_remove_device(struct device *dev,
200 class_device_unregister(&ic->classdev); 206 class_device_unregister(&ic->classdev);
201 } 207 }
202 } 208 }
209 spin_unlock(&cont->containers_lock);
203 } 210 }
204 up(&attribute_container_mutex); 211 up(&attribute_container_mutex);
205} 212}
@@ -230,10 +237,12 @@ attribute_container_device_trigger(struct device *dev,
230 if (!cont->match(cont, dev)) 237 if (!cont->match(cont, dev))
231 continue; 238 continue;
232 239
240 spin_lock(&cont->containers_lock);
233 list_for_each_entry_safe(ic, tmp, &cont->containers, node) { 241 list_for_each_entry_safe(ic, tmp, &cont->containers, node) {
234 if (dev == ic->classdev.dev) 242 if (dev == ic->classdev.dev)
235 fn(cont, dev, &ic->classdev); 243 fn(cont, dev, &ic->classdev);
236 } 244 }
245 spin_unlock(&cont->containers_lock);
237 } 246 }
238 up(&attribute_container_mutex); 247 up(&attribute_container_mutex);
239} 248}
@@ -368,6 +377,35 @@ attribute_container_class_device_del(struct class_device *classdev)
368} 377}
369EXPORT_SYMBOL_GPL(attribute_container_class_device_del); 378EXPORT_SYMBOL_GPL(attribute_container_class_device_del);
370 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 */
389struct class_device *
390attribute_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}
407EXPORT_SYMBOL_GPL(attribute_container_find_class_device);
408
371int __init 409int __init
372attribute_container_init(void) 410attribute_container_init(void)
373{ 411{
diff --git a/drivers/base/transport_class.c b/drivers/base/transport_class.c
index 6c2b447a3336..4fb4c5de8470 100644
--- a/drivers/base/transport_class.c
+++ b/drivers/base/transport_class.c
@@ -64,7 +64,9 @@ void transport_class_unregister(struct transport_class *tclass)
64} 64}
65EXPORT_SYMBOL_GPL(transport_class_unregister); 65EXPORT_SYMBOL_GPL(transport_class_unregister);
66 66
67static int anon_transport_dummy_function(struct device *dev) 67static int anon_transport_dummy_function(struct transport_container *tc,
68 struct device *dev,
69 struct class_device *cdev)
68{ 70{
69 /* do nothing */ 71 /* do nothing */
70 return 0; 72 return 0;
@@ -115,9 +117,10 @@ static int transport_setup_classdev(struct attribute_container *cont,
115 struct class_device *classdev) 117 struct class_device *classdev)
116{ 118{
117 struct transport_class *tclass = class_to_transport_class(cont->class); 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 if (tclass->setup) 122 if (tclass->setup)
120 tclass->setup(dev); 123 tclass->setup(tcont, dev, classdev);
121 124
122 return 0; 125 return 0;
123} 126}
@@ -178,12 +181,14 @@ void transport_add_device(struct device *dev)
178EXPORT_SYMBOL_GPL(transport_add_device); 181EXPORT_SYMBOL_GPL(transport_add_device);
179 182
180static int transport_configure(struct attribute_container *cont, 183static int transport_configure(struct attribute_container *cont,
181 struct device *dev) 184 struct device *dev,
185 struct class_device *cdev)
182{ 186{
183 struct transport_class *tclass = class_to_transport_class(cont->class); 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 if (tclass->configure) 190 if (tclass->configure)
186 tclass->configure(dev); 191 tclass->configure(tcont, dev, cdev);
187 192
188 return 0; 193 return 0;
189} 194}
@@ -202,7 +207,7 @@ static int transport_configure(struct attribute_container *cont,
202 */ 207 */
203void transport_configure_device(struct device *dev) 208void 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}
207EXPORT_SYMBOL_GPL(transport_configure_device); 212EXPORT_SYMBOL_GPL(transport_configure_device);
208 213
@@ -215,7 +220,7 @@ static int transport_remove_classdev(struct attribute_container *cont,
215 struct transport_class *tclass = class_to_transport_class(cont->class); 220 struct transport_class *tclass = class_to_transport_class(cont->class);
216 221
217 if (tclass->remove) 222 if (tclass->remove)
218 tclass->remove(dev); 223 tclass->remove(tcont, dev, classdev);
219 224
220 if (tclass->remove != anon_transport_dummy_function) { 225 if (tclass->remove != anon_transport_dummy_function) {
221 if (tcont->statistics) 226 if (tcont->statistics)
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 35d1c1e8e345..96243c7fe110 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -252,7 +252,8 @@ struct fc_internal {
252 252
253#define to_fc_internal(tmpl) container_of(tmpl, struct fc_internal, t) 253#define to_fc_internal(tmpl) container_of(tmpl, struct fc_internal, t)
254 254
255static int fc_target_setup(struct device *dev) 255static int fc_target_setup(struct transport_container *tc, struct device *dev,
256 struct class_device *cdev)
256{ 257{
257 struct scsi_target *starget = to_scsi_target(dev); 258 struct scsi_target *starget = to_scsi_target(dev);
258 struct fc_rport *rport = starget_to_rport(starget); 259 struct fc_rport *rport = starget_to_rport(starget);
@@ -281,7 +282,8 @@ static DECLARE_TRANSPORT_CLASS(fc_transport_class,
281 NULL, 282 NULL,
282 NULL); 283 NULL);
283 284
284static int fc_host_setup(struct device *dev) 285static int fc_host_setup(struct transport_container *tc, struct device *dev,
286 struct class_device *cdev)
285{ 287{
286 struct Scsi_Host *shost = dev_to_shost(dev); 288 struct Scsi_Host *shost = dev_to_shost(dev);
287 289
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
index 02134fce2174..89f6b7feb9c2 100644
--- a/drivers/scsi/scsi_transport_spi.c
+++ b/drivers/scsi/scsi_transport_spi.c
@@ -162,7 +162,8 @@ static inline enum spi_signal_type spi_signal_to_value(const char *name)
162 return SPI_SIGNAL_UNKNOWN; 162 return SPI_SIGNAL_UNKNOWN;
163} 163}
164 164
165static int spi_host_setup(struct device *dev) 165static int spi_host_setup(struct transport_container *tc, struct device *dev,
166 struct class_device *cdev)
166{ 167{
167 struct Scsi_Host *shost = dev_to_shost(dev); 168 struct Scsi_Host *shost = dev_to_shost(dev);
168 169
@@ -196,7 +197,9 @@ static int spi_host_match(struct attribute_container *cont,
196 return &i->t.host_attrs.ac == cont; 197 return &i->t.host_attrs.ac == cont;
197} 198}
198 199
199static int spi_device_configure(struct device *dev) 200static int spi_device_configure(struct transport_container *tc,
201 struct device *dev,
202 struct class_device *cdev)
200{ 203{
201 struct scsi_device *sdev = to_scsi_device(dev); 204 struct scsi_device *sdev = to_scsi_device(dev);
202 struct scsi_target *starget = sdev->sdev_target; 205 struct scsi_target *starget = sdev->sdev_target;
@@ -214,7 +217,9 @@ static int spi_device_configure(struct device *dev)
214 return 0; 217 return 0;
215} 218}
216 219
217static int spi_setup_transport_attrs(struct device *dev) 220static int spi_setup_transport_attrs(struct transport_container *tc,
221 struct device *dev,
222 struct class_device *cdev)
218{ 223{
219 struct scsi_target *starget = to_scsi_target(dev); 224 struct scsi_target *starget = to_scsi_target(dev);
220 225
diff --git a/include/linux/attribute_container.h b/include/linux/attribute_container.h
index af1010b6dab7..f54b05b052b3 100644
--- a/include/linux/attribute_container.h
+++ b/include/linux/attribute_container.h
@@ -11,10 +11,12 @@
11 11
12#include <linux/device.h> 12#include <linux/device.h>
13#include <linux/list.h> 13#include <linux/list.h>
14#include <linux/spinlock.h>
14 15
15struct attribute_container { 16struct attribute_container {
16 struct list_head node; 17 struct list_head node;
17 struct list_head containers; 18 struct list_head containers;
19 spinlock_t containers_lock;
18 struct class *class; 20 struct class *class;
19 struct class_device_attribute **attrs; 21 struct class_device_attribute **attrs;
20 int (*match)(struct attribute_container *, struct device *); 22 int (*match)(struct attribute_container *, struct device *);
@@ -62,12 +64,7 @@ int attribute_container_add_class_device_adapter(struct attribute_container *con
62 struct class_device *classdev); 64 struct class_device *classdev);
63void attribute_container_remove_attrs(struct class_device *classdev); 65void attribute_container_remove_attrs(struct class_device *classdev);
64void attribute_container_class_device_del(struct class_device *classdev); 66void attribute_container_class_device_del(struct class_device *classdev);
65 67struct class_device *attribute_container_find_class_device(struct attribute_container *, struct device *);
66
67
68
69
70
71struct class_device_attribute **attribute_container_classdev_to_attrs(const struct class_device *classdev); 68struct class_device_attribute **attribute_container_classdev_to_attrs(const struct class_device *classdev);
72 69
73#endif 70#endif
diff --git a/include/linux/transport_class.h b/include/linux/transport_class.h
index 87d98d1faefb..1d6cc22e5f42 100644
--- a/include/linux/transport_class.h
+++ b/include/linux/transport_class.h
@@ -12,11 +12,16 @@
12#include <linux/device.h> 12#include <linux/device.h>
13#include <linux/attribute_container.h> 13#include <linux/attribute_container.h>
14 14
15struct transport_container;
16
15struct transport_class { 17struct transport_class {
16 struct class class; 18 struct class class;
17 int (*setup)(struct device *); 19 int (*setup)(struct transport_container *, struct device *,
18 int (*configure)(struct device *); 20 struct class_device *);
19 int (*remove)(struct 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#define DECLARE_TRANSPORT_CLASS(cls, nm, su, rm, cfg) \ 27#define DECLARE_TRANSPORT_CLASS(cls, nm, su, rm, cfg) \