aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pcmcia')
-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/pcmcia_resource.c76
-rw-r--r--drivers/pcmcia/socket_sysfs.c13
5 files changed, 89 insertions, 32 deletions
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index f804b45de242..fe789e0e7ada 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -266,13 +266,13 @@ EXPORT_SYMBOL(pcmcia_write_cis_mem);
266======================================================================*/ 266======================================================================*/
267 267
268static void read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr, 268static void read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr,
269 u_int len, void *ptr) 269 size_t len, void *ptr)
270{ 270{
271 struct cis_cache_entry *cis; 271 struct cis_cache_entry *cis;
272 int ret; 272 int ret;
273 273
274 if (s->fake_cis) { 274 if (s->fake_cis) {
275 if (s->fake_cis_len > addr+len) 275 if (s->fake_cis_len >= addr+len)
276 memcpy(ptr, s->fake_cis+addr, len); 276 memcpy(ptr, s->fake_cis+addr, len);
277 else 277 else
278 memset(ptr, 0xff, len); 278 memset(ptr, 0xff, len);
@@ -381,17 +381,17 @@ int verify_cis_cache(struct pcmcia_socket *s)
381 381
382======================================================================*/ 382======================================================================*/
383 383
384int pcmcia_replace_cis(struct pcmcia_socket *s, cisdump_t *cis) 384int pcmcia_replace_cis(struct pcmcia_socket *s,
385 const u8 *data, const size_t len)
385{ 386{
386 kfree(s->fake_cis); 387 if (len > CISTPL_MAX_CIS_SIZE)
387 s->fake_cis = NULL;
388 if (cis->Length > CISTPL_MAX_CIS_SIZE)
389 return CS_BAD_SIZE; 388 return CS_BAD_SIZE;
390 s->fake_cis = kmalloc(cis->Length, GFP_KERNEL); 389 kfree(s->fake_cis);
390 s->fake_cis = kmalloc(len, GFP_KERNEL);
391 if (s->fake_cis == NULL) 391 if (s->fake_cis == NULL)
392 return CS_OUT_OF_RESOURCE; 392 return CS_OUT_OF_RESOURCE;
393 s->fake_cis_len = cis->Length; 393 s->fake_cis_len = len;
394 memcpy(s->fake_cis, cis->Data, cis->Length); 394 memcpy(s->fake_cis, data, len);
395 return CS_SUCCESS; 395 return CS_SUCCESS;
396} 396}
397EXPORT_SYMBOL(pcmcia_replace_cis); 397EXPORT_SYMBOL(pcmcia_replace_cis);
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 6501a968a640..a393501554ac 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -864,7 +864,6 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)
864 int ret = -ENOMEM; 864 int ret = -ENOMEM;
865 int no_funcs; 865 int no_funcs;
866 int old_funcs; 866 int old_funcs;
867 cisdump_t *cis;
868 cistpl_longlink_mfc_t mfc; 867 cistpl_longlink_mfc_t mfc;
869 868
870 if (!filename) 869 if (!filename)
@@ -889,16 +888,7 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)
889 goto release; 888 goto release;
890 } 889 }
891 890
892 cis = kzalloc(sizeof(cisdump_t), GFP_KERNEL); 891 if (!pcmcia_replace_cis(s, fw->data, fw->size))
893 if (!cis) {
894 ret = -ENOMEM;
895 goto release;
896 }
897
898 cis->Length = fw->size + 1;
899 memcpy(cis->Data, fw->data, fw->size);
900
901 if (!pcmcia_replace_cis(s, cis))
902 ret = 0; 892 ret = 0;
903 else { 893 else {
904 dev_printk(KERN_ERR, &dev->dev, 894 dev_printk(KERN_ERR, &dev->dev,
diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c
index 0492d2df01a1..f555a505214f 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/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index 2c636058f493..9afe420c41f4 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -912,3 +912,79 @@ void pcmcia_disable_device(struct pcmcia_device *p_dev) {
912 pcmcia_release_window(p_dev->win); 912 pcmcia_release_window(p_dev->win);
913} 913}
914EXPORT_SYMBOL(pcmcia_disable_device); 914EXPORT_SYMBOL(pcmcia_disable_device);
915
916
917struct pcmcia_cfg_mem {
918 tuple_t tuple;
919 cisparse_t parse;
920 u8 buf[256];
921 cistpl_cftable_entry_t dflt;
922};
923
924/**
925 * pcmcia_loop_config() - loop over configuration options
926 * @p_dev: the struct pcmcia_device which we need to loop for.
927 * @conf_check: function to call for each configuration option.
928 * It gets passed the struct pcmcia_device, the CIS data
929 * describing the configuration option, and private data
930 * being passed to pcmcia_loop_config()
931 * @priv_data: private data to be passed to the conf_check function.
932 *
933 * pcmcia_loop_config() loops over all configuration options, and calls
934 * the driver-specific conf_check() for each one, checking whether
935 * it is a valid one.
936 */
937int pcmcia_loop_config(struct pcmcia_device *p_dev,
938 int (*conf_check) (struct pcmcia_device *p_dev,
939 cistpl_cftable_entry_t *cfg,
940 cistpl_cftable_entry_t *dflt,
941 unsigned int vcc,
942 void *priv_data),
943 void *priv_data)
944{
945 struct pcmcia_cfg_mem *cfg_mem;
946
947 tuple_t *tuple;
948 int ret = -ENODEV;
949 unsigned int vcc;
950
951 cfg_mem = kzalloc(sizeof(struct pcmcia_cfg_mem), GFP_KERNEL);
952 if (cfg_mem == NULL)
953 return -ENOMEM;
954
955 /* get the current Vcc setting */
956 vcc = p_dev->socket->socket.Vcc;
957
958 tuple = &cfg_mem->tuple;
959 tuple->TupleData = cfg_mem->buf;
960 tuple->TupleDataMax = 255;
961 tuple->TupleOffset = 0;
962 tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
963 tuple->Attributes = 0;
964
965 ret = pcmcia_get_first_tuple(p_dev, tuple);
966 while (!ret) {
967 cistpl_cftable_entry_t *cfg = &cfg_mem->parse.cftable_entry;
968
969 if (pcmcia_get_tuple_data(p_dev, tuple))
970 goto next_entry;
971
972 if (pcmcia_parse_tuple(p_dev, tuple, &cfg_mem->parse))
973 goto next_entry;
974
975 /* default values */
976 p_dev->conf.ConfigIndex = cfg->index;
977 if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
978 cfg_mem->dflt = *cfg;
979
980 ret = conf_check(p_dev, cfg, &cfg_mem->dflt, vcc, priv_data);
981 if (!ret)
982 break;
983
984next_entry:
985 ret = pcmcia_get_next_tuple(p_dev, tuple);
986 }
987
988 return ret;
989}
990EXPORT_SYMBOL(pcmcia_loop_config);
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