[PATCH 01/39] pcmcia: only copy CIS override data once

Dominik Brodowski linux at dominikbrodowski.net
Mon Aug 18 14:52:52 EDT 2008


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 at dominikbrodowski.net>
---
 drivers/pcmcia/cistpl.c       |   18 +++++++++---------
 drivers/pcmcia/ds.c           |   12 +-----------
 drivers/pcmcia/pcmcia_ioctl.c |    2 +-
 drivers/pcmcia/socket_sysfs.c |   13 ++-----------
 include/pcmcia/cistpl.h       |   10 ++--------
 include/pcmcia/ds.h           |    6 ++++++
 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 65129b5..11c473c 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -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);
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 4174d96..2382341 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)
 	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");
diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c
index 419f97f..6c086ff 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,
 			   &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)) {
diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c
index 006a29e..ff9a3bb 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,
 				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;
 
diff --git a/include/pcmcia/cistpl.h b/include/pcmcia/cistpl.h
index e2e10c1..552a332 100644
--- a/include/pcmcia/cistpl.h
+++ b/include/pcmcia/cistpl.h
@@ -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);
diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h
index b316027..2d36a4f 100644
--- a/include/pcmcia/ds.h
+++ b/include/pcmcia/ds.h
@@ -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;
diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h
index ed919dd..e34bef0 100644
--- a/include/pcmcia/ss.h
+++ b/include/pcmcia/ss.h
@@ -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;
-- 
1.5.4.3




More information about the linux-pcmcia mailing list