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: Dominik Brodowski <linux@dominikbrodowski.net>
This commit is contained in:
@@ -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)
|
|||||||
|
|
||||||
======================================================================*/
|
======================================================================*/
|
||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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,
|
|||||||
&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,
|
|||||||
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 {
|
|||||||
|
|
||||||
#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 {
|
|||||||
#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 {
|
|||||||
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;
|
||||||
|
Reference in New Issue
Block a user