From: Dominik Brodowski 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 Signed-off-by: Andrew Morton --- 25-akpm/drivers/pcmcia/cs_internal.h | 1 25-akpm/drivers/pcmcia/ds.c | 6 ++++ 25-akpm/drivers/pcmcia/socket_sysfs.c | 47 +++++++++++++++++++++++++++++++++- 3 files changed, 53 insertions(+), 1 deletion(-) diff -puN drivers/pcmcia/cs_internal.h~pcmcia-cis-overrid-via-sysfs drivers/pcmcia/cs_internal.h --- 25/drivers/pcmcia/cs_internal.h~pcmcia-cis-overrid-via-sysfs Sun Mar 6 17:28:07 2005 +++ 25-akpm/drivers/pcmcia/cs_internal.h Sun Mar 6 17:28:07 2005 @@ -160,6 +160,7 @@ struct pcmcia_callback{ struct module *owner; int (*event) (struct pcmcia_socket *s, event_t event, int priority); int (*resources_done) (struct pcmcia_socket *s); + void (*replace_cis) (void); }; int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c); diff -puN drivers/pcmcia/ds.c~pcmcia-cis-overrid-via-sysfs drivers/pcmcia/ds.c --- 25/drivers/pcmcia/ds.c~pcmcia-cis-overrid-via-sysfs Sun Mar 6 17:28:07 2005 +++ 25-akpm/drivers/pcmcia/ds.c Sun Mar 6 17:28:07 2005 @@ -653,6 +653,11 @@ static inline void pcmcia_add_pseudo_dev return; } +static void pcmcia_bus_rescan(void) +{ + /* must be called with skt_sem held */ + bus_rescan_devices(&pcmcia_bus_type); +} static inline int pcmcia_devmatch(struct pcmcia_device *dev, struct pcmcia_device_id *did) @@ -1764,6 +1769,7 @@ static int __devinit pcmcia_bus_add_sock s->callback.owner = THIS_MODULE; s->callback.event = &ds_event; s->callback.resources_done = &pcmcia_card_add; + s->callback.replace_cis = &pcmcia_bus_rescan; socket->pcmcia = s; ret = pccard_register_pcmcia(socket, &s->callback); diff -puN drivers/pcmcia/socket_sysfs.c~pcmcia-cis-overrid-via-sysfs drivers/pcmcia/socket_sysfs.c --- 25/drivers/pcmcia/socket_sysfs.c~pcmcia-cis-overrid-via-sysfs Sun Mar 6 17:28:07 2005 +++ 25-akpm/drivers/pcmcia/socket_sysfs.c Sun Mar 6 17:28:07 2005 @@ -282,6 +282,50 @@ static ssize_t pccard_show_cis(struct ko return (count); } +static ssize_t pccard_store_cis(struct kobject *kobj, char *buf, loff_t off, size_t count) +{ + struct pcmcia_socket *s = to_socket(container_of(kobj, struct class_device, kobj)); + cisdump_t *cis; + ssize_t ret = count; + + if (off) + return -EINVAL; + + if (count >= 0x200) + return -EINVAL; + + if (!(s->state & SOCKET_PRESENT)) + return -ENODEV; + + cis = kmalloc(sizeof(cisdump_t), GFP_KERNEL); + if (!cis) + return -ENOMEM; + memset(cis, 0, sizeof(cisdump_t)); + + cis->Length = count + 1; + memcpy(cis->Data, buf, count); + + if (pcmcia_replace_cis(s, cis)) + ret = -EIO; + + kfree(cis); + + if (!ret) { + down(&s->skt_sem); + if ((s->callback) && (s->state & SOCKET_PRESENT) && + !(s->state & SOCKET_CARDBUS)) { + if (try_module_get(s->callback->owner)) { + s->callback->replace_cis(); + module_put(s->callback->owner); + } + } + up(&s->skt_sem); + } + + + return (ret); +} + static struct class_device_attribute *pccard_socket_attributes[] = { &class_device_attr_card_type, @@ -296,9 +340,10 @@ static struct class_device_attribute *pc }; static struct bin_attribute pccard_cis_attr = { - .attr = { .name = "cis", .mode = S_IRUGO, .owner = THIS_MODULE}, + .attr = { .name = "cis", .mode = S_IRUGO | S_IWUSR, .owner = THIS_MODULE}, .size = 0x200, .read = pccard_show_cis, + .write = pccard_store_cis, }; static int __devinit pccard_sysfs_add_socket(struct class_device *class_dev) _