提交 53efec95 编写于 作者: D Dominik Brodowski

pcmcia: only copy CIS override data once

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: NDominik Brodowski <linux@dominikbrodowski.net>
上级 6e86841d
...@@ -265,13 +265,13 @@ EXPORT_SYMBOL(pcmcia_write_cis_mem); ...@@ -265,13 +265,13 @@ EXPORT_SYMBOL(pcmcia_write_cis_mem);
======================================================================*/ ======================================================================*/
static void read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr, 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; struct cis_cache_entry *cis;
int ret; int ret;
if (s->fake_cis) { 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); memcpy(ptr, s->fake_cis+addr, len);
else else
memset(ptr, 0xff, len); memset(ptr, 0xff, len);
...@@ -380,17 +380,17 @@ int verify_cis_cache(struct pcmcia_socket *s) ...@@ -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); if (len > CISTPL_MAX_CIS_SIZE)
s->fake_cis = NULL;
if (cis->Length > CISTPL_MAX_CIS_SIZE)
return CS_BAD_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) if (s->fake_cis == NULL)
return CS_OUT_OF_RESOURCE; return CS_OUT_OF_RESOURCE;
s->fake_cis_len = cis->Length; s->fake_cis_len = len;
memcpy(s->fake_cis, cis->Data, cis->Length); memcpy(s->fake_cis, data, len);
return CS_SUCCESS; return CS_SUCCESS;
} }
EXPORT_SYMBOL(pcmcia_replace_cis); EXPORT_SYMBOL(pcmcia_replace_cis);
......
...@@ -854,7 +854,6 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename) ...@@ -854,7 +854,6 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)
int ret = -ENOMEM; int ret = -ENOMEM;
int no_funcs; int no_funcs;
int old_funcs; int old_funcs;
cisdump_t *cis;
cistpl_longlink_mfc_t mfc; cistpl_longlink_mfc_t mfc;
if (!filename) if (!filename)
...@@ -877,16 +876,7 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename) ...@@ -877,16 +876,7 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)
goto release; goto release;
} }
cis = kzalloc(sizeof(cisdump_t), GFP_KERNEL); if (!pcmcia_replace_cis(s, fw->data, fw->size))
if (!cis) {
ret = -ENOMEM;
goto release;
}
cis->Length = fw->size + 1;
memcpy(cis->Data, fw->data, fw->size);
if (!pcmcia_replace_cis(s, cis))
ret = 0; ret = 0;
else { else {
printk(KERN_ERR "pcmcia: CIS override failed\n"); printk(KERN_ERR "pcmcia: CIS override failed\n");
......
...@@ -867,7 +867,7 @@ static int ds_ioctl(struct inode * inode, struct file * file, ...@@ -867,7 +867,7 @@ static int ds_ioctl(struct inode * inode, struct file * file,
&buf->win_info.map); &buf->win_info.map);
break; break;
case DS_REPLACE_CIS: case DS_REPLACE_CIS:
ret = pcmcia_replace_cis(s, &buf->cisdump); ret = pcmcia_replace_cis(s, buf->cisdump.Data, buf->cisdump.Length);
break; break;
case DS_BIND_REQUEST: case DS_BIND_REQUEST:
if (!capable(CAP_SYS_ADMIN)) { if (!capable(CAP_SYS_ADMIN)) {
......
...@@ -316,27 +316,18 @@ static ssize_t pccard_store_cis(struct kobject *kobj, ...@@ -316,27 +316,18 @@ static ssize_t pccard_store_cis(struct kobject *kobj,
char *buf, loff_t off, size_t count) char *buf, loff_t off, size_t count)
{ {
struct pcmcia_socket *s = to_socket(container_of(kobj, struct device, kobj)); struct pcmcia_socket *s = to_socket(container_of(kobj, struct device, kobj));
cisdump_t *cis;
int error; int error;
if (off) if (off)
return -EINVAL; return -EINVAL;
if (count >= 0x200) if (count >= CISTPL_MAX_CIS_SIZE)
return -EINVAL; return -EINVAL;
if (!(s->state & SOCKET_PRESENT)) if (!(s->state & SOCKET_PRESENT))
return -ENODEV; return -ENODEV;
cis = kzalloc(sizeof(cisdump_t), GFP_KERNEL); error = pcmcia_replace_cis(s, buf, count);
if (!cis)
return -ENOMEM;
cis->Length = count + 1;
memcpy(cis->Data, buf, count);
error = pcmcia_replace_cis(s, cis);
kfree(cis);
if (error) if (error)
return -EIO; return -EIO;
......
...@@ -580,14 +580,8 @@ typedef struct cisinfo_t { ...@@ -580,14 +580,8 @@ typedef struct cisinfo_t {
#define CISTPL_MAX_CIS_SIZE 0x200 #define CISTPL_MAX_CIS_SIZE 0x200
/* For ReplaceCIS */ int pcmcia_replace_cis(struct pcmcia_socket *s,
typedef struct cisdump_t { const u8 *data, const size_t len);
u_int Length;
cisdata_t Data[CISTPL_MAX_CIS_SIZE];
} cisdump_t;
int pcmcia_replace_cis(struct pcmcia_socket *s, cisdump_t *cis);
/* don't use outside of PCMCIA core yet */ /* don't use outside of PCMCIA core yet */
int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int func, tuple_t *tuple); int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int func, tuple_t *tuple);
......
...@@ -68,6 +68,12 @@ typedef struct region_info_t { ...@@ -68,6 +68,12 @@ typedef struct region_info_t {
#define REGION_BAR_MASK 0xe000 #define REGION_BAR_MASK 0xe000
#define REGION_BAR_SHIFT 13 #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 { typedef union ds_ioctl_arg_t {
adjust_t adjust; adjust_t adjust;
config_info_t config; config_info_t config;
......
...@@ -199,8 +199,8 @@ struct pcmcia_socket { ...@@ -199,8 +199,8 @@ struct pcmcia_socket {
io_window_t io[MAX_IO_WIN]; io_window_t io[MAX_IO_WIN];
window_t win[MAX_WIN]; window_t win[MAX_WIN];
struct list_head cis_cache; struct list_head cis_cache;
u_int fake_cis_len; size_t fake_cis_len;
char *fake_cis; u8 *fake_cis;
struct list_head socket_list; struct list_head socket_list;
struct completion socket_released; struct completion socket_released;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册