diff options
author | Dominik Brodowski <linux@dominikbrodowski.net> | 2005-06-27 19:28:09 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-27 21:03:07 -0400 |
commit | ff1fa9ef3c9fb23a6baa06b63f4bdf3de089b29a (patch) | |
tree | 05cd82cc6bbb4c9881de5d9c5584cc64f15262d1 /drivers/pcmcia/socket_sysfs.c | |
parent | 7f299bccb422d707be3b074f9a669b34cb207a14 (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>
Diffstat (limited to 'drivers/pcmcia/socket_sysfs.c')
-rw-r--r-- | drivers/pcmcia/socket_sysfs.c | 47 |
1 files changed, 46 insertions, 1 deletions
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 | ||
285 | static 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 | ||
286 | static struct class_device_attribute *pccard_socket_attributes[] = { | 330 | static 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 | ||
298 | static struct bin_attribute pccard_cis_attr = { | 342 | static 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 | ||
304 | static int __devinit pccard_sysfs_add_socket(struct class_device *class_dev) | 349 | static int __devinit pccard_sysfs_add_socket(struct class_device *class_dev) |