Commit 83e410b8 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://bk.arm.linux.org.uk/linux-2.5-pcmcia

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 70ced8bf 41c5d533
...@@ -35,7 +35,6 @@ ...@@ -35,7 +35,6 @@
#include <pcmcia/cistpl.h> #include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h> #include <pcmcia/cisreg.h>
#include <pcmcia/ds.h> #include <pcmcia/ds.h>
#include <pcmcia/bus_ops.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/io.h> #include <asm/io.h>
......
...@@ -123,7 +123,7 @@ static u_int xlate_rom_addr(u_char * b, u_int addr) ...@@ -123,7 +123,7 @@ static u_int xlate_rom_addr(u_char * b, u_int addr)
=====================================================================*/ =====================================================================*/
void cb_release_cis_mem(socket_info_t * s) static void cb_release_cis_mem(socket_info_t * s)
{ {
if (s->cb_cis_virt) { if (s->cb_cis_virt) {
DEBUG(1, "cs: cb_release_cis_mem()\n"); DEBUG(1, "cs: cb_release_cis_mem()\n");
...@@ -270,6 +270,8 @@ void cb_free(socket_info_t * s) ...@@ -270,6 +270,8 @@ void cb_free(socket_info_t * s)
{ {
struct pci_dev *bridge = s->cap.cb_dev; struct pci_dev *bridge = s->cap.cb_dev;
cb_release_cis_mem(s);
if (bridge) if (bridge)
pci_remove_behind_bridge(bridge); pci_remove_behind_bridge(bridge);
} }
...@@ -269,8 +269,8 @@ void write_cis_mem(socket_info_t *s, int attr, u_int addr, ...@@ -269,8 +269,8 @@ void write_cis_mem(socket_info_t *s, int attr, u_int addr,
static void read_cis_cache(socket_info_t *s, int attr, u_int addr, static void read_cis_cache(socket_info_t *s, int attr, u_int addr,
u_int len, void *ptr) u_int len, void *ptr)
{ {
int i, ret; struct cis_cache_entry *cis;
char *caddr; int ret;
if (s->fake_cis) { if (s->fake_cis) {
if (s->fake_cis_len > addr+len) if (s->fake_cis_len > addr+len)
...@@ -279,31 +279,54 @@ static void read_cis_cache(socket_info_t *s, int attr, u_int addr, ...@@ -279,31 +279,54 @@ static void read_cis_cache(socket_info_t *s, int attr, u_int addr,
memset(ptr, 0xff, len); memset(ptr, 0xff, len);
return; return;
} }
caddr = s->cis_cache;
for (i = 0; i < s->cis_used; i++) { list_for_each_entry(cis, &s->cis_cache, node) {
if ((s->cis_table[i].addr == addr) && if (cis->addr == addr && cis->len == len && cis->attr == attr) {
(s->cis_table[i].len == len) && memcpy(ptr, cis->cache, len);
(s->cis_table[i].attr == attr)) break;
caddr += s->cis_table[i].len;
}
if (i < s->cis_used) {
memcpy(ptr, caddr, len);
return; return;
} }
}
#ifdef CONFIG_CARDBUS #ifdef CONFIG_CARDBUS
if (s->state & SOCKET_CARDBUS) if (s->state & SOCKET_CARDBUS)
ret = read_cb_mem(s, attr, addr, len, ptr); ret = read_cb_mem(s, attr, addr, len, ptr);
else else
#endif #endif
ret = read_cis_mem(s, attr, addr, len, ptr); ret = read_cis_mem(s, attr, addr, len, ptr);
/* Copy data into the cache, if there is room */
if ((ret == 0) && (i < MAX_CIS_TABLE) && /* Copy data into the cache */
(caddr+len < s->cis_cache+MAX_CIS_DATA)) { cis = kmalloc(sizeof(struct cis_cache_entry) + len, GFP_KERNEL);
s->cis_table[i].addr = addr; if (cis) {
s->cis_table[i].len = len; cis->addr = addr;
s->cis_table[i].attr = attr; cis->len = len;
s->cis_used++; cis->attr = attr;
memcpy(caddr, ptr, len); memcpy(cis->cache, ptr, len);
list_add(&cis->node, &s->cis_cache);
}
}
static void
remove_cis_cache(socket_info_t *s, int attr, u_int addr, u_int len)
{
struct cis_cache_entry *cis;
list_for_each_entry(cis, &s->cis_cache, node)
if (cis->addr == addr && cis->len == len && cis->attr == attr) {
list_del(&cis->node);
kfree(cis);
break;
}
}
void destroy_cis_cache(socket_info_t *s)
{
struct list_head *l, *n;
list_for_each_safe(l, n, &s->cis_cache) {
struct cis_cache_entry *cis = list_entry(l, struct cis_cache_entry, node);
list_del(&cis->node);
kfree(cis);
} }
} }
...@@ -316,24 +339,25 @@ static void read_cis_cache(socket_info_t *s, int attr, u_int addr, ...@@ -316,24 +339,25 @@ static void read_cis_cache(socket_info_t *s, int attr, u_int addr,
int verify_cis_cache(socket_info_t *s) int verify_cis_cache(socket_info_t *s)
{ {
char buf[256], *caddr; struct cis_cache_entry *cis;
int i; char buf[256];
list_for_each_entry(cis, &s->cis_cache, node) {
int len = cis->len;
caddr = s->cis_cache; if (len > 256)
for (i = 0; i < s->cis_used; i++) { len = 256;
#ifdef CONFIG_CARDBUS #ifdef CONFIG_CARDBUS
if (s->state & SOCKET_CARDBUS) if (s->state & SOCKET_CARDBUS)
read_cb_mem(s, s->cis_table[i].attr, s->cis_table[i].addr, read_cb_mem(s, cis->attr, cis->addr, len, buf);
s->cis_table[i].len, buf);
else else
#endif #endif
read_cis_mem(s, s->cis_table[i].attr, s->cis_table[i].addr, read_cis_mem(s, cis->attr, cis->addr, len, buf);
s->cis_table[i].len, buf);
if (memcmp(buf, caddr, s->cis_table[i].len) != 0) if (memcmp(buf, cis->cache, len) != 0)
break; return -1;
caddr += s->cis_table[i].len;
} }
return (i < s->cis_used); return 0;
} }
/*====================================================================== /*======================================================================
...@@ -449,14 +473,16 @@ static int follow_link(socket_info_t *s, tuple_t *tuple) ...@@ -449,14 +473,16 @@ static int follow_link(socket_info_t *s, tuple_t *tuple)
if ((link[0] == CISTPL_LINKTARGET) && (link[1] >= 3) && if ((link[0] == CISTPL_LINKTARGET) && (link[1] >= 3) &&
(strncmp(link+2, "CIS", 3) == 0)) (strncmp(link+2, "CIS", 3) == 0))
return ofs; return ofs;
remove_cis_cache(s, SPACE(tuple->Flags), ofs, 5);
/* Then, we try the wrong spot... */ /* Then, we try the wrong spot... */
ofs = ofs >> 1; ofs = ofs >> 1;
} }
read_cis_cache(s, SPACE(tuple->Flags), ofs, 5, link); read_cis_cache(s, SPACE(tuple->Flags), ofs, 5, link);
if ((link[0] != CISTPL_LINKTARGET) || (link[1] < 3) || if ((link[0] == CISTPL_LINKTARGET) && (link[1] >= 3) &&
(strncmp(link+2, "CIS", 3) != 0)) (strncmp(link+2, "CIS", 3) == 0))
return -1;
return ofs; return ofs;
remove_cis_cache(s, SPACE(tuple->Flags), ofs, 5);
return -1;
} }
int pcmcia_get_next_tuple(client_handle_t handle, tuple_t *tuple) int pcmcia_get_next_tuple(client_handle_t handle, tuple_t *tuple)
......
...@@ -342,6 +342,7 @@ int pcmcia_register_socket(struct device *dev) ...@@ -342,6 +342,7 @@ int pcmcia_register_socket(struct device *dev)
s->cis_mem.flags = 0; s->cis_mem.flags = 0;
s->cis_mem.speed = cis_speed; s->cis_mem.speed = cis_speed;
s->erase_busy.next = s->erase_busy.prev = &s->erase_busy; s->erase_busy.next = s->erase_busy.prev = &s->erase_busy;
INIT_LIST_HEAD(&s->cis_cache);
spin_lock_init(&s->lock); spin_lock_init(&s->lock);
/* TBD: remove usage of socket_table, use class_for_each_dev instead */ /* TBD: remove usage of socket_table, use class_for_each_dev instead */
...@@ -469,7 +470,7 @@ static void shutdown_socket(socket_info_t *s) ...@@ -469,7 +470,7 @@ static void shutdown_socket(socket_info_t *s)
init_socket(s); init_socket(s);
s->irq.AssignedIRQ = s->irq.Config = 0; s->irq.AssignedIRQ = s->irq.Config = 0;
s->lock_count = 0; s->lock_count = 0;
s->cis_used = 0; destroy_cis_cache(s);
if (s->fake_cis) { if (s->fake_cis) {
kfree(s->fake_cis); kfree(s->fake_cis);
s->fake_cis = NULL; s->fake_cis = NULL;
...@@ -484,7 +485,6 @@ static void shutdown_socket(socket_info_t *s) ...@@ -484,7 +485,6 @@ static void shutdown_socket(socket_info_t *s)
set_socket(s, &s->socket); set_socket(s, &s->socket);
/* */ /* */
#ifdef CONFIG_CARDBUS #ifdef CONFIG_CARDBUS
cb_release_cis_mem(s);
cb_free(s); cb_free(s);
#endif #endif
s->functions = 0; s->functions = 0;
......
...@@ -114,9 +114,13 @@ typedef struct config_t { ...@@ -114,9 +114,13 @@ typedef struct config_t {
/* Maximum number of memory windows per socket */ /* Maximum number of memory windows per socket */
#define MAX_WIN 4 #define MAX_WIN 4
/* The size of the CIS cache */ struct cis_cache_entry {
#define MAX_CIS_TABLE 64 struct list_head node;
#define MAX_CIS_DATA 512 unsigned int addr;
unsigned int len;
unsigned int attr;
unsigned char cache[0];
};
typedef struct socket_info_t { typedef struct socket_info_t {
spinlock_t lock; spinlock_t lock;
...@@ -145,13 +149,7 @@ typedef struct socket_info_t { ...@@ -145,13 +149,7 @@ typedef struct socket_info_t {
window_t win[MAX_WIN]; window_t win[MAX_WIN];
region_t *c_region, *a_region; region_t *c_region, *a_region;
erase_busy_t erase_busy; erase_busy_t erase_busy;
int cis_used; struct list_head cis_cache;
struct {
u_int addr;
u_short len;
u_short attr;
} cis_table[MAX_CIS_TABLE];
char cis_cache[MAX_CIS_DATA];
u_int fake_cis_len; u_int fake_cis_len;
char *fake_cis; char *fake_cis;
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
...@@ -198,7 +196,6 @@ typedef struct socket_info_t { ...@@ -198,7 +196,6 @@ typedef struct socket_info_t {
int cb_alloc(socket_info_t *s); int cb_alloc(socket_info_t *s);
void cb_free(socket_info_t *s); void cb_free(socket_info_t *s);
int read_cb_mem(socket_info_t *s, int space, u_int addr, u_int len, void *ptr); int read_cb_mem(socket_info_t *s, int space, u_int addr, u_int len, void *ptr);
void cb_release_cis_mem(socket_info_t *s);
/* In cistpl.c */ /* In cistpl.c */
int read_cis_mem(socket_info_t *s, int attr, int read_cis_mem(socket_info_t *s, int attr,
...@@ -206,6 +203,7 @@ int read_cis_mem(socket_info_t *s, int attr, ...@@ -206,6 +203,7 @@ int read_cis_mem(socket_info_t *s, int attr,
void write_cis_mem(socket_info_t *s, int attr, void write_cis_mem(socket_info_t *s, int attr,
u_int addr, u_int len, void *ptr); u_int addr, u_int len, void *ptr);
void release_cis_mem(socket_info_t *s); void release_cis_mem(socket_info_t *s);
void destroy_cis_cache(socket_info_t *s);
int verify_cis_cache(socket_info_t *s); int verify_cis_cache(socket_info_t *s);
void preload_cis_cache(socket_info_t *s); void preload_cis_cache(socket_info_t *s);
int get_first_tuple(client_handle_t handle, tuple_t *tuple); int get_first_tuple(client_handle_t handle, tuple_t *tuple);
......
...@@ -351,7 +351,7 @@ static int cis_readable(socket_info_t *s, u_long base) ...@@ -351,7 +351,7 @@ static int cis_readable(socket_info_t *s, u_long base)
ret = pcmcia_validate_cis(s->clients, &info1); ret = pcmcia_validate_cis(s->clients, &info1);
/* invalidate mapping and CIS cache */ /* invalidate mapping and CIS cache */
iounmap(s->cis_virt); iounmap(s->cis_virt);
s->cis_used = 0; destroy_cis_cache(s);
if ((ret != 0) || (info1.Chains == 0)) if ((ret != 0) || (info1.Chains == 0))
return 0; return 0;
s->cis_mem.sys_start = base+s->cap.map_size; s->cis_mem.sys_start = base+s->cap.map_size;
...@@ -359,7 +359,7 @@ static int cis_readable(socket_info_t *s, u_long base) ...@@ -359,7 +359,7 @@ static int cis_readable(socket_info_t *s, u_long base)
s->cis_virt = ioremap(base+s->cap.map_size, s->cap.map_size); s->cis_virt = ioremap(base+s->cap.map_size, s->cap.map_size);
ret = pcmcia_validate_cis(s->clients, &info2); ret = pcmcia_validate_cis(s->clients, &info2);
iounmap(s->cis_virt); iounmap(s->cis_virt);
s->cis_used = 0; destroy_cis_cache(s);
return ((ret == 0) && (info1.Chains == info2.Chains)); return ((ret == 0) && (info1.Chains == info2.Chains));
} }
...@@ -499,14 +499,16 @@ void validate_mem(socket_info_t *s) ...@@ -499,14 +499,16 @@ void validate_mem(socket_info_t *s)
void validate_mem(socket_info_t *s) void validate_mem(socket_info_t *s)
{ {
resource_map_t *m; resource_map_t *m, *n;
static int done = 0; static int done = 0;
if (probe_mem && done++ == 0) { if (probe_mem && done++ == 0) {
down(&rsrc_sem); down(&rsrc_sem);
for (m = mem_db.next; m != &mem_db; m = m->next) for (m = mem_db.next; m != &mem_db; m = n) {
n = m->next;
if (do_mem_probe(m->base, m->num, s)) if (do_mem_probe(m->base, m->num, s))
break; break;
}
up(&rsrc_sem); up(&rsrc_sem);
} }
} }
...@@ -743,9 +745,6 @@ static int adjust_memory(adjust_t *adj) ...@@ -743,9 +745,6 @@ static int adjust_memory(adjust_t *adj)
if (ret == CS_SUCCESS) { if (ret == CS_SUCCESS) {
for (i = 0; i < sockets; i++) { for (i = 0; i < sockets; i++) {
release_cis_mem(socket_table[i]); release_cis_mem(socket_table[i]);
#ifdef CONFIG_CARDBUS
cb_release_cis_mem(socket_table[i]);
#endif
} }
} }
break; break;
......
/* now empty */
#warning please remove the reference to this file
/* now empty */
#warning please remove the reference to this file
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
#define _LINUX_DS_H #define _LINUX_DS_H
#include <pcmcia/bulkmem.h> #include <pcmcia/bulkmem.h>
#include <linux/device.h>
#include <pcmcia/cs_types.h> #include <pcmcia/cs_types.h>
typedef struct tuple_parse_t { typedef struct tuple_parse_t {
...@@ -107,6 +106,7 @@ typedef union ds_ioctl_arg_t { ...@@ -107,6 +106,7 @@ typedef union ds_ioctl_arg_t {
#define DS_BIND_MTD _IOWR('d', 64, mtd_info_t) #define DS_BIND_MTD _IOWR('d', 64, mtd_info_t)
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <linux/device.h>
typedef struct dev_node_t { typedef struct dev_node_t {
char dev_name[DEV_NAME_LEN]; char dev_name[DEV_NAME_LEN];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment