pcmcia: only copy CIS override data once
Dominik Brodowski [Mon, 28 Jul 2008 17:44:05 +0000 (19:44 +0200)]
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>

drivers/pcmcia/cistpl.c
drivers/pcmcia/ds.c
drivers/pcmcia/pcmcia_ioctl.c
drivers/pcmcia/socket_sysfs.c
include/pcmcia/cistpl.h
include/pcmcia/ds.h
include/pcmcia/ss.h

index 65129b5..11c473c 100644 (file)
@@ -265,13 +265,13 @@ EXPORT_SYMBOL(pcmcia_write_cis_mem);
 ======================================================================*/
 
 static void read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr,
-                          u_int len, void *ptr)
+                          size_t len, void *ptr)
 {
     struct cis_cache_entry *cis;
     int ret;
 
     if (s->fake_cis) {
-       if (s->fake_cis_len > addr+len)
+       if (s->fake_cis_len >= addr+len)
            memcpy(ptr, s->fake_cis+addr, len);
        else
            memset(ptr, 0xff, len);
@@ -380,17 +380,17 @@ int verify_cis_cache(struct pcmcia_socket *s)
     
 ======================================================================*/
 
-int pcmcia_replace_cis(struct pcmcia_socket *s, cisdump_t *cis)
+int pcmcia_replace_cis(struct pcmcia_socket *s,
+                      const u8 *data, const size_t len)
 {
-    kfree(s->fake_cis);
-    s->fake_cis = NULL;
-    if (cis->Length > CISTPL_MAX_CIS_SIZE)
+    if (len > CISTPL_MAX_CIS_SIZE)
        return CS_BAD_SIZE;
-    s->fake_cis = kmalloc(cis->Length, GFP_KERNEL);
+    kfree(s->fake_cis);
+    s->fake_cis = kmalloc(len, GFP_KERNEL);
     if (s->fake_cis == NULL)
        return CS_OUT_OF_RESOURCE;
-    s->fake_cis_len = cis->Length;
-    memcpy(s->fake_cis, cis->Data, cis->Length);
+    s->fake_cis_len = len;
+    memcpy(s->fake_cis, data, len);
     return CS_SUCCESS;
 }
 EXPORT_SYMBOL(pcmcia_replace_cis);
index 4174d96..2382341 100644 (file)
@@ -854,7 +854,6 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)
        int ret = -ENOMEM;
        int no_funcs;
        int old_funcs;
-       cisdump_t *cis;
        cistpl_longlink_mfc_t mfc;
 
        if (!filename)
@@ -877,16 +876,7 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)
                        goto release;
                }
 
-               cis = kzalloc(sizeof(cisdump_t), GFP_KERNEL);
-               if (!cis) {
-                       ret = -ENOMEM;
-                       goto release;
-               }
-
-               cis->Length = fw->size + 1;
-               memcpy(cis->Data, fw->data, fw->size);
-
-               if (!pcmcia_replace_cis(s, cis))
+               if (!pcmcia_replace_cis(s, fw->data, fw->size))
                        ret = 0;
                else {
                        printk(KERN_ERR "pcmcia: CIS override failed\n");
index 419f97f..6c086ff 100644 (file)
@@ -867,7 +867,7 @@ static int ds_ioctl(struct inode * inode, struct file * file,
                           &buf->win_info.map);
        break;
     case DS_REPLACE_CIS:
-       ret = pcmcia_replace_cis(s, &buf->cisdump);
+       ret = pcmcia_replace_cis(s, buf->cisdump.Data, buf->cisdump.Length);
        break;
     case DS_BIND_REQUEST:
        if (!capable(CAP_SYS_ADMIN)) {
index 006a29e..ff9a3bb 100644 (file)
@@ -316,27 +316,18 @@ 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 device, kobj));
-       cisdump_t *cis;
        int error;
 
        if (off)
                return -EINVAL;
 
-       if (count >= 0x200)
+       if (count >= CISTPL_MAX_CIS_SIZE)
                return -EINVAL;
 
        if (!(s->state & SOCKET_PRESENT))
                return -ENODEV;
 
-       cis = kzalloc(sizeof(cisdump_t), GFP_KERNEL);
-       if (!cis)
-               return -ENOMEM;
-
-       cis->Length = count + 1;
-       memcpy(cis->Data, buf, count);
-
-       error = pcmcia_replace_cis(s, cis);
-       kfree(cis);
+       error = pcmcia_replace_cis(s, buf, count);
        if (error)
                return -EIO;
 
index e2e10c1..552a332 100644 (file)
@@ -580,14 +580,8 @@ typedef struct cisinfo_t {
 
 #define CISTPL_MAX_CIS_SIZE    0x200
 
-/* For ReplaceCIS */
-typedef struct cisdump_t {
-    u_int      Length;
-    cisdata_t  Data[CISTPL_MAX_CIS_SIZE];
-} cisdump_t;
-
-
-int pcmcia_replace_cis(struct pcmcia_socket *s, cisdump_t *cis);
+int pcmcia_replace_cis(struct pcmcia_socket *s,
+                      const u8 *data, const size_t len);
 
 /* don't use outside of PCMCIA core yet */
 int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int func, tuple_t *tuple);
index b316027..2d36a4f 100644 (file)
@@ -68,6 +68,12 @@ typedef struct region_info_t {
 #define REGION_BAR_MASK                0xe000
 #define REGION_BAR_SHIFT       13
 
+/* For ReplaceCIS */
+typedef struct cisdump_t {
+    u_int      Length;
+    cisdata_t  Data[CISTPL_MAX_CIS_SIZE];
+} cisdump_t;
+
 typedef union ds_ioctl_arg_t {
     adjust_t           adjust;
     config_info_t      config;
index ed919dd..e34bef0 100644 (file)
@@ -199,8 +199,8 @@ struct pcmcia_socket {
        io_window_t                     io[MAX_IO_WIN];
        window_t                        win[MAX_WIN];
        struct list_head                cis_cache;
-       u_int                           fake_cis_len;
-       char                            *fake_cis;
+       size_t                          fake_cis_len;
+       u8                              *fake_cis;
 
        struct list_head                socket_list;
        struct completion               socket_released;