aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2005-06-27 19:28:09 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-27 21:03:07 -0400
commitff1fa9ef3c9fb23a6baa06b63f4bdf3de089b29a (patch)
tree05cd82cc6bbb4c9881de5d9c5584cc64f15262d1
parent7f299bccb422d707be3b074f9a669b34cb207a14 (diff)
[PATCH] pcmcia: CIS overrid via sysfs
The one thing which surprises me in this patch that cis->Length needs to be set to count+1. Without it, it doesn't work, but with it, it doesn't make sense to me. Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--drivers/pcmcia/cs_internal.h1
-rw-r--r--drivers/pcmcia/ds.c6
-rw-r--r--drivers/pcmcia/socket_sysfs.c47
3 files changed, 53 insertions, 1 deletions
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index 7933a7db49d3..211637390fbc 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -160,6 +160,7 @@ struct pcmcia_callback{
160 struct module *owner; 160 struct module *owner;
161 int (*event) (struct pcmcia_socket *s, event_t event, int priority); 161 int (*event) (struct pcmcia_socket *s, event_t event, int priority);
162 int (*resources_done) (struct pcmcia_socket *s); 162 int (*resources_done) (struct pcmcia_socket *s);
163 void (*replace_cis) (void);
163}; 164};
164 165
165int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c); 166int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c);
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index c0611d56eab2..f657a2a77b2b 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -653,6 +653,11 @@ static inline void pcmcia_add_pseudo_device(struct pcmcia_bus_socket *s)
653 return; 653 return;
654} 654}
655 655
656static void pcmcia_bus_rescan(void)
657{
658 /* must be called with skt_sem held */
659 bus_rescan_devices(&pcmcia_bus_type);
660}
656 661
657static inline int pcmcia_devmatch(struct pcmcia_device *dev, 662static inline int pcmcia_devmatch(struct pcmcia_device *dev,
658 struct pcmcia_device_id *did) 663 struct pcmcia_device_id *did)
@@ -1766,6 +1771,7 @@ static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev)
1766 s->callback.owner = THIS_MODULE; 1771 s->callback.owner = THIS_MODULE;
1767 s->callback.event = &ds_event; 1772 s->callback.event = &ds_event;
1768 s->callback.resources_done = &pcmcia_card_add; 1773 s->callback.resources_done = &pcmcia_card_add;
1774 s->callback.replace_cis = &pcmcia_bus_rescan;
1769 socket->pcmcia = s; 1775 socket->pcmcia = s;
1770 1776
1771 ret = pccard_register_pcmcia(socket, &s->callback); 1777 ret = pccard_register_pcmcia(socket, &s->callback);
diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c
index fd5a3b0557b3..8e66eeff672e 100644
--- a/drivers/pcmcia/socket_sysfs.c
+++ b/drivers/pcmcia/socket_sysfs.c
@@ -282,6 +282,50 @@ static ssize_t pccard_show_cis(struct kobject *kobj, char *buf, loff_t off, size
282 return (count); 282 return (count);
283} 283}
284 284
285static ssize_t pccard_store_cis(struct kobject *kobj, char *buf, loff_t off, size_t count)
286{
287 struct pcmcia_socket *s = to_socket(container_of(kobj, struct class_device, kobj));
288 cisdump_t *cis;
289 ssize_t ret = count;
290
291 if (off)
292 return -EINVAL;
293
294 if (count >= 0x200)
295 return -EINVAL;
296
297 if (!(s->state & SOCKET_PRESENT))
298 return -ENODEV;
299
300 cis = kmalloc(sizeof(cisdump_t), GFP_KERNEL);
301 if (!cis)
302 return -ENOMEM;
303 memset(cis, 0, sizeof(cisdump_t));
304
305 cis->Length = count + 1;
306 memcpy(cis->Data, buf, count);
307
308 if (pcmcia_replace_cis(s, cis))
309 ret = -EIO;
310
311 kfree(cis);
312
313 if (!ret) {
314 down(&s->skt_sem);
315 if ((s->callback) && (s->state & SOCKET_PRESENT) &&
316 !(s->state & SOCKET_CARDBUS)) {
317 if (try_module_get(s->callback->owner)) {
318 s->callback->replace_cis();
319 module_put(s->callback->owner);
320 }
321 }
322 up(&s->skt_sem);
323 }
324
325
326 return (ret);
327}
328
285 329
286static struct class_device_attribute *pccard_socket_attributes[] = { 330static struct class_device_attribute *pccard_socket_attributes[] = {
287 &class_device_attr_card_type, 331 &class_device_attr_card_type,
@@ -296,9 +340,10 @@ static struct class_device_attribute *pccard_socket_attributes[] = {
296}; 340};
297 341
298static struct bin_attribute pccard_cis_attr = { 342static struct bin_attribute pccard_cis_attr = {
299 .attr = { .name = "cis", .mode = S_IRUGO, .owner = THIS_MODULE}, 343 .attr = { .name = "cis", .mode = S_IRUGO | S_IWUSR, .owner = THIS_MODULE},
300 .size = 0x200, 344 .size = 0x200,
301 .read = pccard_show_cis, 345 .read = pccard_show_cis,
346 .write = pccard_store_cis,
302}; 347};
303 348
304static int __devinit pccard_sysfs_add_socket(struct class_device *class_dev) 349static int __devinit pccard_sysfs_add_socket(struct class_device *class_dev)