diff options
Diffstat (limited to 'drivers/pcmcia')
-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/pcmcia_resource.c | 76 | ||||
-rw-r--r-- | drivers/pcmcia/socket_sysfs.c | 13 |
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 | ||
268 | static void read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr, | 268 | static 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 | ||
384 | int pcmcia_replace_cis(struct pcmcia_socket *s, cisdump_t *cis) | 384 | int 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 | } |
397 | EXPORT_SYMBOL(pcmcia_replace_cis); | 397 | EXPORT_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 | } |
914 | EXPORT_SYMBOL(pcmcia_disable_device); | 914 | EXPORT_SYMBOL(pcmcia_disable_device); |
915 | |||
916 | |||
917 | struct 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 | */ | ||
937 | int 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 | |||
984 | next_entry: | ||
985 | ret = pcmcia_get_next_tuple(p_dev, tuple); | ||
986 | } | ||
987 | |||
988 | return ret; | ||
989 | } | ||
990 | EXPORT_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 | ||