aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pcmcia/cistpl.c18
-rw-r--r--drivers/pcmcia/ds.c12
-rw-r--r--drivers/pcmcia/pcmcia_ioctl.c2
-rw-r--r--drivers/pcmcia/socket_sysfs.c13
-rw-r--r--include/pcmcia/cistpl.h10
-rw-r--r--include/pcmcia/ds.h6
-rw-r--r--include/pcmcia/ss.h4
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
267static void read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr, 267static 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
383int pcmcia_replace_cis(struct pcmcia_socket *s, cisdump_t *cis) 383int 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}
396EXPORT_SYMBOL(pcmcia_replace_cis); 396EXPORT_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 */ 583int pcmcia_replace_cis(struct pcmcia_socket *s,
584typedef 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
590int 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 */
593int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int func, tuple_t *tuple); 587int 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 */
72typedef struct cisdump_t {
73 u_int Length;
74 cisdata_t Data[CISTPL_MAX_CIS_SIZE];
75} cisdump_t;
76
71typedef union ds_ioctl_arg_t { 77typedef 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;