diff options
author | Dominik Brodowski <linux@dominikbrodowski.net> | 2008-07-28 13:44:05 -0400 |
---|---|---|
committer | Dominik Brodowski <linux@dominikbrodowski.net> | 2008-08-02 12:56:49 -0400 |
commit | 53efec9513cfb1acff602c7ebdd945d677808e9e (patch) | |
tree | 6bf9d0475d0be0829348096442d505001c027017 | |
parent | 6e86841d05f371b5b9b86ce76c02aaee83352298 (diff) |
pcmcia: only copy CIS override data once
Instead of copying CIS override data in socket_sysfs.c or ds.c, and then again
in cistpl.c, only do so once. Also, cisdump_t is now only used by the
deprecated ioctl.
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
-rw-r--r-- | drivers/pcmcia/cistpl.c | 18 | ||||
-rw-r--r-- | drivers/pcmcia/ds.c | 12 | ||||
-rw-r--r-- | drivers/pcmcia/pcmcia_ioctl.c | 2 | ||||
-rw-r--r-- | drivers/pcmcia/socket_sysfs.c | 13 | ||||
-rw-r--r-- | include/pcmcia/cistpl.h | 10 | ||||
-rw-r--r-- | include/pcmcia/ds.h | 6 | ||||
-rw-r--r-- | include/pcmcia/ss.h | 4 |
7 files changed, 23 insertions, 42 deletions
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index 65129b54eb09..11c473c865a5 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c | |||
@@ -265,13 +265,13 @@ EXPORT_SYMBOL(pcmcia_write_cis_mem); | |||
265 | ======================================================================*/ | 265 | ======================================================================*/ |
266 | 266 | ||
267 | static void read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr, | 267 | static void read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr, |
268 | u_int len, void *ptr) | 268 | size_t len, void *ptr) |
269 | { | 269 | { |
270 | struct cis_cache_entry *cis; | 270 | struct cis_cache_entry *cis; |
271 | int ret; | 271 | int ret; |
272 | 272 | ||
273 | if (s->fake_cis) { | 273 | if (s->fake_cis) { |
274 | if (s->fake_cis_len > addr+len) | 274 | if (s->fake_cis_len >= addr+len) |
275 | memcpy(ptr, s->fake_cis+addr, len); | 275 | memcpy(ptr, s->fake_cis+addr, len); |
276 | else | 276 | else |
277 | memset(ptr, 0xff, len); | 277 | memset(ptr, 0xff, len); |
@@ -380,17 +380,17 @@ int verify_cis_cache(struct pcmcia_socket *s) | |||
380 | 380 | ||
381 | ======================================================================*/ | 381 | ======================================================================*/ |
382 | 382 | ||
383 | int pcmcia_replace_cis(struct pcmcia_socket *s, cisdump_t *cis) | 383 | int pcmcia_replace_cis(struct pcmcia_socket *s, |
384 | const u8 *data, const size_t len) | ||
384 | { | 385 | { |
385 | kfree(s->fake_cis); | 386 | if (len > CISTPL_MAX_CIS_SIZE) |
386 | s->fake_cis = NULL; | ||
387 | if (cis->Length > CISTPL_MAX_CIS_SIZE) | ||
388 | return CS_BAD_SIZE; | 387 | return CS_BAD_SIZE; |
389 | s->fake_cis = kmalloc(cis->Length, GFP_KERNEL); | 388 | kfree(s->fake_cis); |
389 | s->fake_cis = kmalloc(len, GFP_KERNEL); | ||
390 | if (s->fake_cis == NULL) | 390 | if (s->fake_cis == NULL) |
391 | return CS_OUT_OF_RESOURCE; | 391 | return CS_OUT_OF_RESOURCE; |
392 | s->fake_cis_len = cis->Length; | 392 | s->fake_cis_len = len; |
393 | memcpy(s->fake_cis, cis->Data, cis->Length); | 393 | memcpy(s->fake_cis, data, len); |
394 | return CS_SUCCESS; | 394 | return CS_SUCCESS; |
395 | } | 395 | } |
396 | EXPORT_SYMBOL(pcmcia_replace_cis); | 396 | EXPORT_SYMBOL(pcmcia_replace_cis); |
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 4174d9656e35..2382341975e5 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
@@ -854,7 +854,6 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename) | |||
854 | int ret = -ENOMEM; | 854 | int ret = -ENOMEM; |
855 | int no_funcs; | 855 | int no_funcs; |
856 | int old_funcs; | 856 | int old_funcs; |
857 | cisdump_t *cis; | ||
858 | cistpl_longlink_mfc_t mfc; | 857 | cistpl_longlink_mfc_t mfc; |
859 | 858 | ||
860 | if (!filename) | 859 | if (!filename) |
@@ -877,16 +876,7 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename) | |||
877 | goto release; | 876 | goto release; |
878 | } | 877 | } |
879 | 878 | ||
880 | cis = kzalloc(sizeof(cisdump_t), GFP_KERNEL); | 879 | if (!pcmcia_replace_cis(s, fw->data, fw->size)) |
881 | if (!cis) { | ||
882 | ret = -ENOMEM; | ||
883 | goto release; | ||
884 | } | ||
885 | |||
886 | cis->Length = fw->size + 1; | ||
887 | memcpy(cis->Data, fw->data, fw->size); | ||
888 | |||
889 | if (!pcmcia_replace_cis(s, cis)) | ||
890 | ret = 0; | 880 | ret = 0; |
891 | else { | 881 | else { |
892 | printk(KERN_ERR "pcmcia: CIS override failed\n"); | 882 | printk(KERN_ERR "pcmcia: CIS override failed\n"); |
diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c index 419f97fc9a62..6c086ffea448 100644 --- a/drivers/pcmcia/pcmcia_ioctl.c +++ b/drivers/pcmcia/pcmcia_ioctl.c | |||
@@ -867,7 +867,7 @@ static int ds_ioctl(struct inode * inode, struct file * file, | |||
867 | &buf->win_info.map); | 867 | &buf->win_info.map); |
868 | break; | 868 | break; |
869 | case DS_REPLACE_CIS: | 869 | case DS_REPLACE_CIS: |
870 | ret = pcmcia_replace_cis(s, &buf->cisdump); | 870 | ret = pcmcia_replace_cis(s, buf->cisdump.Data, buf->cisdump.Length); |
871 | break; | 871 | break; |
872 | case DS_BIND_REQUEST: | 872 | case DS_BIND_REQUEST: |
873 | if (!capable(CAP_SYS_ADMIN)) { | 873 | if (!capable(CAP_SYS_ADMIN)) { |
diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c index 006a29e91d83..ff9a3bb3c88d 100644 --- a/drivers/pcmcia/socket_sysfs.c +++ b/drivers/pcmcia/socket_sysfs.c | |||
@@ -316,27 +316,18 @@ static ssize_t pccard_store_cis(struct kobject *kobj, | |||
316 | char *buf, loff_t off, size_t count) | 316 | char *buf, loff_t off, size_t count) |
317 | { | 317 | { |
318 | struct pcmcia_socket *s = to_socket(container_of(kobj, struct device, kobj)); | 318 | struct pcmcia_socket *s = to_socket(container_of(kobj, struct device, kobj)); |
319 | cisdump_t *cis; | ||
320 | int error; | 319 | int error; |
321 | 320 | ||
322 | if (off) | 321 | if (off) |
323 | return -EINVAL; | 322 | return -EINVAL; |
324 | 323 | ||
325 | if (count >= 0x200) | 324 | if (count >= CISTPL_MAX_CIS_SIZE) |
326 | return -EINVAL; | 325 | return -EINVAL; |
327 | 326 | ||
328 | if (!(s->state & SOCKET_PRESENT)) | 327 | if (!(s->state & SOCKET_PRESENT)) |
329 | return -ENODEV; | 328 | return -ENODEV; |
330 | 329 | ||
331 | cis = kzalloc(sizeof(cisdump_t), GFP_KERNEL); | 330 | error = pcmcia_replace_cis(s, buf, count); |
332 | if (!cis) | ||
333 | return -ENOMEM; | ||
334 | |||
335 | cis->Length = count + 1; | ||
336 | memcpy(cis->Data, buf, count); | ||
337 | |||
338 | error = pcmcia_replace_cis(s, cis); | ||
339 | kfree(cis); | ||
340 | if (error) | 331 | if (error) |
341 | return -EIO; | 332 | return -EIO; |
342 | 333 | ||
diff --git a/include/pcmcia/cistpl.h b/include/pcmcia/cistpl.h index e2e10c1e9a06..552a332ad714 100644 --- a/include/pcmcia/cistpl.h +++ b/include/pcmcia/cistpl.h | |||
@@ -580,14 +580,8 @@ typedef struct cisinfo_t { | |||
580 | 580 | ||
581 | #define CISTPL_MAX_CIS_SIZE 0x200 | 581 | #define CISTPL_MAX_CIS_SIZE 0x200 |
582 | 582 | ||
583 | /* For ReplaceCIS */ | 583 | int pcmcia_replace_cis(struct pcmcia_socket *s, |
584 | typedef struct cisdump_t { | 584 | const u8 *data, const size_t len); |
585 | u_int Length; | ||
586 | cisdata_t Data[CISTPL_MAX_CIS_SIZE]; | ||
587 | } cisdump_t; | ||
588 | |||
589 | |||
590 | int pcmcia_replace_cis(struct pcmcia_socket *s, cisdump_t *cis); | ||
591 | 585 | ||
592 | /* don't use outside of PCMCIA core yet */ | 586 | /* don't use outside of PCMCIA core yet */ |
593 | int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int func, tuple_t *tuple); | 587 | int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int func, tuple_t *tuple); |
diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h index b316027c853d..2d36a4f80e5b 100644 --- a/include/pcmcia/ds.h +++ b/include/pcmcia/ds.h | |||
@@ -68,6 +68,12 @@ typedef struct region_info_t { | |||
68 | #define REGION_BAR_MASK 0xe000 | 68 | #define REGION_BAR_MASK 0xe000 |
69 | #define REGION_BAR_SHIFT 13 | 69 | #define REGION_BAR_SHIFT 13 |
70 | 70 | ||
71 | /* For ReplaceCIS */ | ||
72 | typedef struct cisdump_t { | ||
73 | u_int Length; | ||
74 | cisdata_t Data[CISTPL_MAX_CIS_SIZE]; | ||
75 | } cisdump_t; | ||
76 | |||
71 | typedef union ds_ioctl_arg_t { | 77 | typedef union ds_ioctl_arg_t { |
72 | adjust_t adjust; | 78 | adjust_t adjust; |
73 | config_info_t config; | 79 | config_info_t config; |
diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h index ed919dd9bb5c..e34bef0fc74f 100644 --- a/include/pcmcia/ss.h +++ b/include/pcmcia/ss.h | |||
@@ -199,8 +199,8 @@ struct pcmcia_socket { | |||
199 | io_window_t io[MAX_IO_WIN]; | 199 | io_window_t io[MAX_IO_WIN]; |
200 | window_t win[MAX_WIN]; | 200 | window_t win[MAX_WIN]; |
201 | struct list_head cis_cache; | 201 | struct list_head cis_cache; |
202 | u_int fake_cis_len; | 202 | size_t fake_cis_len; |
203 | char *fake_cis; | 203 | u8 *fake_cis; |
204 | 204 | ||
205 | struct list_head socket_list; | 205 | struct list_head socket_list; |
206 | struct completion socket_released; | 206 | struct completion socket_released; |