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 @@
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
#include <pcmcia/bus_ops.h>
#include <asm/uaccess.h>
#include <asm/io.h>
......
......@@ -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) {
DEBUG(1, "cs: cb_release_cis_mem()\n");
......@@ -270,6 +270,8 @@ void cb_free(socket_info_t * s)
{
struct pci_dev *bridge = s->cap.cb_dev;
cb_release_cis_mem(s);
if (bridge)
pci_remove_behind_bridge(bridge);
}
......@@ -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,
u_int len, void *ptr)
{
int i, ret;
char *caddr;
struct cis_cache_entry *cis;
int ret;
if (s->fake_cis) {
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,
memset(ptr, 0xff, len);
return;
}
caddr = s->cis_cache;
for (i = 0; i < s->cis_used; i++) {
if ((s->cis_table[i].addr == addr) &&
(s->cis_table[i].len == len) &&
(s->cis_table[i].attr == attr)) break;
caddr += s->cis_table[i].len;
}
if (i < s->cis_used) {
memcpy(ptr, caddr, len);
list_for_each_entry(cis, &s->cis_cache, node) {
if (cis->addr == addr && cis->len == len && cis->attr == attr) {
memcpy(ptr, cis->cache, len);
return;
}
}
#ifdef CONFIG_CARDBUS
if (s->state & SOCKET_CARDBUS)
ret = read_cb_mem(s, attr, addr, len, ptr);
else
#endif
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) &&
(caddr+len < s->cis_cache+MAX_CIS_DATA)) {
s->cis_table[i].addr = addr;
s->cis_table[i].len = len;
s->cis_table[i].attr = attr;
s->cis_used++;
memcpy(caddr, ptr, len);
/* Copy data into the cache */
cis = kmalloc(sizeof(struct cis_cache_entry) + len, GFP_KERNEL);
if (cis) {
cis->addr = addr;
cis->len = len;
cis->attr = attr;
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,
int verify_cis_cache(socket_info_t *s)
{
char buf[256], *caddr;
int i;
struct cis_cache_entry *cis;
char buf[256];
list_for_each_entry(cis, &s->cis_cache, node) {
int len = cis->len;
caddr = s->cis_cache;
for (i = 0; i < s->cis_used; i++) {
if (len > 256)
len = 256;
#ifdef CONFIG_CARDBUS
if (s->state & SOCKET_CARDBUS)
read_cb_mem(s, s->cis_table[i].attr, s->cis_table[i].addr,
s->cis_table[i].len, buf);
read_cb_mem(s, cis->attr, cis->addr, len, buf);
else
#endif
read_cis_mem(s, s->cis_table[i].attr, s->cis_table[i].addr,
s->cis_table[i].len, buf);
if (memcmp(buf, caddr, s->cis_table[i].len) != 0)
break;
caddr += s->cis_table[i].len;
read_cis_mem(s, cis->attr, cis->addr, len, buf);
if (memcmp(buf, cis->cache, len) != 0)
return -1;
}
return (i < s->cis_used);
return 0;
}
/*======================================================================
......@@ -449,14 +473,16 @@ static int follow_link(socket_info_t *s, tuple_t *tuple)
if ((link[0] == CISTPL_LINKTARGET) && (link[1] >= 3) &&
(strncmp(link+2, "CIS", 3) == 0))
return ofs;
remove_cis_cache(s, SPACE(tuple->Flags), ofs, 5);
/* Then, we try the wrong spot... */
ofs = ofs >> 1;
}
read_cis_cache(s, SPACE(tuple->Flags), ofs, 5, link);
if ((link[0] != CISTPL_LINKTARGET) || (link[1] < 3) ||
(strncmp(link+2, "CIS", 3) != 0))
return -1;
if ((link[0] == CISTPL_LINKTARGET) && (link[1] >= 3) &&
(strncmp(link+2, "CIS", 3) == 0))
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)
......
......@@ -342,6 +342,7 @@ int pcmcia_register_socket(struct device *dev)
s->cis_mem.flags = 0;
s->cis_mem.speed = cis_speed;
s->erase_busy.next = s->erase_busy.prev = &s->erase_busy;
INIT_LIST_HEAD(&s->cis_cache);
spin_lock_init(&s->lock);
/* TBD: remove usage of socket_table, use class_for_each_dev instead */
......@@ -469,7 +470,7 @@ static void shutdown_socket(socket_info_t *s)
init_socket(s);
s->irq.AssignedIRQ = s->irq.Config = 0;
s->lock_count = 0;
s->cis_used = 0;
destroy_cis_cache(s);
if (s->fake_cis) {
kfree(s->fake_cis);
s->fake_cis = NULL;
......@@ -484,7 +485,6 @@ static void shutdown_socket(socket_info_t *s)
set_socket(s, &s->socket);
/* */
#ifdef CONFIG_CARDBUS
cb_release_cis_mem(s);
cb_free(s);
#endif
s->functions = 0;
......
......@@ -114,9 +114,13 @@ typedef struct config_t {
/* Maximum number of memory windows per socket */
#define MAX_WIN 4
/* The size of the CIS cache */
#define MAX_CIS_TABLE 64
#define MAX_CIS_DATA 512
struct cis_cache_entry {
struct list_head node;
unsigned int addr;
unsigned int len;
unsigned int attr;
unsigned char cache[0];
};
typedef struct socket_info_t {
spinlock_t lock;
......@@ -145,13 +149,7 @@ typedef struct socket_info_t {
window_t win[MAX_WIN];
region_t *c_region, *a_region;
erase_busy_t erase_busy;
int cis_used;
struct {
u_int addr;
u_short len;
u_short attr;
} cis_table[MAX_CIS_TABLE];
char cis_cache[MAX_CIS_DATA];
struct list_head cis_cache;
u_int fake_cis_len;
char *fake_cis;
#ifdef CONFIG_PROC_FS
......@@ -198,7 +196,6 @@ typedef struct socket_info_t {
int cb_alloc(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);
void cb_release_cis_mem(socket_info_t *s);
/* In cistpl.c */
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,
u_int addr, u_int len, void *ptr);
void release_cis_mem(socket_info_t *s);
void destroy_cis_cache(socket_info_t *s);
int verify_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);
......
......@@ -351,7 +351,7 @@ static int cis_readable(socket_info_t *s, u_long base)
ret = pcmcia_validate_cis(s->clients, &info1);
/* invalidate mapping and CIS cache */
iounmap(s->cis_virt);
s->cis_used = 0;
destroy_cis_cache(s);
if ((ret != 0) || (info1.Chains == 0))
return 0;
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)
s->cis_virt = ioremap(base+s->cap.map_size, s->cap.map_size);
ret = pcmcia_validate_cis(s->clients, &info2);
iounmap(s->cis_virt);
s->cis_used = 0;
destroy_cis_cache(s);
return ((ret == 0) && (info1.Chains == info2.Chains));
}
......@@ -499,14 +499,16 @@ 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;
if (probe_mem && done++ == 0) {
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))
break;
}
up(&rsrc_sem);
}
}
......@@ -743,9 +745,6 @@ static int adjust_memory(adjust_t *adj)
if (ret == CS_SUCCESS) {
for (i = 0; i < sockets; i++) {
release_cis_mem(socket_table[i]);
#ifdef CONFIG_CARDBUS
cb_release_cis_mem(socket_table[i]);
#endif
}
}
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 @@
#define _LINUX_DS_H
#include <pcmcia/bulkmem.h>
#include <linux/device.h>
#include <pcmcia/cs_types.h>
typedef struct tuple_parse_t {
......@@ -107,6 +106,7 @@ typedef union ds_ioctl_arg_t {
#define DS_BIND_MTD _IOWR('d', 64, mtd_info_t)
#ifdef __KERNEL__
#include <linux/device.h>
typedef struct dev_node_t {
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