Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 57197b9b authored by Dominik Brodowski's avatar Dominik Brodowski
Browse files

pcmcia: CardBus doesn't need CIS access



At least no in-kernel CardBus-capable PCI driver makes use of the CIS
access functions. Therefore, it seems sensible to remove this unused
code, and cleanup cardbus.c a lot.

CC: Jesse Barnes <jbarnes@virtuousgeek.org>
CC: Linus Torvalds <torvalds@linux-foundation.org>
Tested-by: default avatarWolfram Sang <w.sang@pengutronix.de>
Signed-off-by: default avatarDominik Brodowski <linux@dominikbrodowski.net>
parent 88b060d6
Loading
Loading
Loading
Loading
+14 −161
Original line number Original line Diff line number Diff line
@@ -20,170 +20,12 @@
 */
 */




#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/pci.h>
#include <linux/pci.h>
#include <linux/ioport.h>
#include <linux/io.h>
#include <asm/irq.h>


#include <pcmcia/cs_types.h>
#include <pcmcia/ss.h>
#include <pcmcia/ss.h>
#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include "cs_internal.h"

/*====================================================================*/

/* Offsets in the Expansion ROM Image Header */
#define ROM_SIGNATURE		0x0000	/* 2 bytes */
#define ROM_DATA_PTR		0x0018	/* 2 bytes */

/* Offsets in the CardBus PC Card Data Structure */
#define PCDATA_SIGNATURE	0x0000	/* 4 bytes */
#define PCDATA_VPD_PTR		0x0008	/* 2 bytes */
#define PCDATA_LENGTH		0x000a	/* 2 bytes */
#define PCDATA_REVISION		0x000c
#define PCDATA_IMAGE_SZ		0x0010	/* 2 bytes */
#define PCDATA_ROM_LEVEL	0x0012	/* 2 bytes */
#define PCDATA_CODE_TYPE	0x0014
#define PCDATA_INDICATOR	0x0015

/*=====================================================================

    Expansion ROM's have a special layout, and pointers specify an
    image number and an offset within that image.  xlate_rom_addr()
    converts an image/offset address to an absolute offset from the
    ROM's base address.

=====================================================================*/

static u_int xlate_rom_addr(void __iomem *b, u_int addr)
{
	u_int img = 0, ofs = 0, sz;
	u_short data;
	while ((readb(b) == 0x55) && (readb(b + 1) == 0xaa)) {
		if (img == (addr >> 28))
			return (addr & 0x0fffffff) + ofs;
		data = readb(b + ROM_DATA_PTR) + (readb(b + ROM_DATA_PTR + 1) << 8);
		sz = 512 * (readb(b + data + PCDATA_IMAGE_SZ) +
			    (readb(b + data + PCDATA_IMAGE_SZ + 1) << 8));
		if ((sz == 0) || (readb(b + data + PCDATA_INDICATOR) & 0x80))
			break;
		b += sz;
		ofs += sz;
		img++;
	}
	return 0;
}

/*=====================================================================

    These are similar to setup_cis_mem and release_cis_mem for 16-bit
    cards.  The "result" that is used externally is the cb_cis_virt
    pointer in the struct pcmcia_socket structure.

=====================================================================*/

static void cb_release_cis_mem(struct pcmcia_socket *s)
{
	if (s->cb_cis_virt) {
		dev_dbg(&s->dev, "cb_release_cis_mem()\n");
		iounmap(s->cb_cis_virt);
		s->cb_cis_virt = NULL;
		s->cb_cis_res = NULL;
	}
}

static int cb_setup_cis_mem(struct pcmcia_socket *s, struct resource *res)
{
	unsigned int start, size;

	if (res == s->cb_cis_res)
		return 0;

	if (s->cb_cis_res)
		cb_release_cis_mem(s);

	start = res->start;
	size = res->end - start + 1;
	s->cb_cis_virt = ioremap(start, size);

	if (!s->cb_cis_virt)
		return -1;

	s->cb_cis_res = res;

	return 0;
}

/*=====================================================================

    This is used by the CIS processing code to read CIS information
    from a CardBus device.

=====================================================================*/

int read_cb_mem(struct pcmcia_socket *s, int space, u_int addr, u_int len,
		void *ptr)
{
	struct pci_dev *dev;
	struct resource *res;

	dev_dbg(&s->dev, "read_cb_mem(%d, %#x, %u)\n", space, addr, len);

	dev = pci_get_slot(s->cb_dev->subordinate, 0);
	if (!dev)
		goto fail;

	/* Config space? */
	if (space == 0) {
		if (addr + len > 0x100)
			goto failput;
		for (; len; addr++, ptr++, len--)
			pci_read_config_byte(dev, addr, ptr);
		return 0;
	}

	res = dev->resource + space - 1;

	pci_dev_put(dev);

	if (!res->flags)
		goto fail;


	if (cb_setup_cis_mem(s, res) != 0)
		goto fail;

	if (space == 7) {
		addr = xlate_rom_addr(s->cb_cis_virt, addr);
		if (addr == 0)
			goto fail;
	}

	if (addr + len > res->end - res->start)
		goto fail;

	memcpy_fromio(ptr, s->cb_cis_virt + addr, len);
	return 0;

failput:
	pci_dev_put(dev);
fail:
	memset(ptr, 0xff, len);
	return -1;
}

/*=====================================================================

    cb_alloc() and cb_free() allocate and free the kernel data
    structures for a Cardbus device, and handle the lowest level PCI
    device setup issues.

=====================================================================*/


static void cardbus_config_irq_and_cls(struct pci_bus *bus, int irq)
static void cardbus_config_irq_and_cls(struct pci_bus *bus, int irq)
{
{
@@ -215,6 +57,13 @@ static void cardbus_config_irq_and_cls(struct pci_bus *bus, int irq)
	}
	}
}
}


/**
 * cb_alloc() - add CardBus device
 * @s:		the pcmcia_socket where the CardBus device is located
 *
 * cb_alloc() allocates the kernel data structures for a Cardbus device
 * and handles the lowest level PCI device setup issues.
 */
int __ref cb_alloc(struct pcmcia_socket *s)
int __ref cb_alloc(struct pcmcia_socket *s)
{
{
	struct pci_bus *bus = s->cb_dev->subordinate;
	struct pci_bus *bus = s->cb_dev->subordinate;
@@ -249,12 +98,16 @@ int __ref cb_alloc(struct pcmcia_socket *s)
	return 0;
	return 0;
}
}


/**
 * cb_free() - remove CardBus device
 * @s:		the pcmcia_socket where the CardBus device was located
 *
 * cb_free() handles the lowest level PCI device cleanup.
 */
void cb_free(struct pcmcia_socket *s)
void cb_free(struct pcmcia_socket *s)
{
{
	struct pci_dev *bridge = s->cb_dev;
	struct pci_dev *bridge = s->cb_dev;


	cb_release_cis_mem(s);

	if (bridge)
	if (bridge)
		pci_remove_behind_bridge(bridge);
		pci_remove_behind_bridge(bridge);
}
}
+32 −168
Original line number Original line Diff line number Diff line
@@ -271,6 +271,9 @@ static void read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr,
	struct cis_cache_entry *cis;
	struct cis_cache_entry *cis;
	int ret;
	int ret;


	if (s->state & SOCKET_CARDBUS)
		return;

	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);
@@ -286,11 +289,6 @@ static void read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr,
		}
		}
	}
	}


#ifdef CONFIG_CARDBUS
    if (s->state & SOCKET_CARDBUS)
	ret = read_cb_mem(s, attr, addr, len, ptr);
    else
#endif
	ret = pcmcia_read_cis_mem(s, attr, addr, len, ptr);
	ret = pcmcia_read_cis_mem(s, attr, addr, len, ptr);


	if (ret == 0) {
	if (ret == 0) {
@@ -351,6 +349,9 @@ int verify_cis_cache(struct pcmcia_socket *s)
	struct cis_cache_entry *cis;
	struct cis_cache_entry *cis;
	char *buf;
	char *buf;


	if (s->state & SOCKET_CARDBUS)
		return -EINVAL;

	buf = kmalloc(256, GFP_KERNEL);
	buf = kmalloc(256, GFP_KERNEL);
	if (buf == NULL) {
	if (buf == NULL) {
		dev_printk(KERN_WARNING, &s->dev,
		dev_printk(KERN_WARNING, &s->dev,
@@ -362,11 +363,7 @@ int verify_cis_cache(struct pcmcia_socket *s)


		if (len > 256)
		if (len > 256)
			len = 256;
			len = 256;
#ifdef CONFIG_CARDBUS

		if (s->state & SOCKET_CARDBUS)
			read_cb_mem(s, cis->attr, cis->addr, len, buf);
		else
#endif
		pcmcia_read_cis_mem(s, cis->attr, cis->addr, len, buf);
		pcmcia_read_cis_mem(s, cis->attr, cis->addr, len, buf);


		if (memcmp(buf, cis->cache, len) != 0) {
		if (memcmp(buf, cis->cache, len) != 0) {
@@ -427,25 +424,16 @@ int pccard_get_first_tuple(struct pcmcia_socket *s, unsigned int function, tuple
{
{
    if (!s)
    if (!s)
	return -EINVAL;
	return -EINVAL;
    if (!(s->state & SOCKET_PRESENT))

    if (!(s->state & SOCKET_PRESENT) || (s->state & SOCKET_CARDBUS))
	return -ENODEV;
	return -ENODEV;
    tuple->TupleLink = tuple->Flags = 0;
    tuple->TupleLink = tuple->Flags = 0;
#ifdef CONFIG_CARDBUS

    if (s->state & SOCKET_CARDBUS) {
	struct pci_dev *dev = s->cb_dev;
	u_int ptr;
	pci_bus_read_config_dword(dev->subordinate, 0, PCI_CARDBUS_CIS, &ptr);
	tuple->CISOffset = ptr & ~7;
	SPACE(tuple->Flags) = (ptr & 7);
    } else
#endif
    {
    /* Assume presence of a LONGLINK_C to address 0 */
    /* Assume presence of a LONGLINK_C to address 0 */
    tuple->CISOffset = tuple->LinkOffset = 0;
    tuple->CISOffset = tuple->LinkOffset = 0;
    SPACE(tuple->Flags) = HAS_LINK(tuple->Flags) = 1;
    SPACE(tuple->Flags) = HAS_LINK(tuple->Flags) = 1;
    }

    if (!(s->state & SOCKET_CARDBUS) && (s->functions > 1) &&
    if ((s->functions > 1) && !(tuple->Attributes & TUPLE_RETURN_COMMON)) {
	!(tuple->Attributes & TUPLE_RETURN_COMMON)) {
	cisdata_t req = tuple->DesiredTuple;
	cisdata_t req = tuple->DesiredTuple;
	tuple->DesiredTuple = CISTPL_LONGLINK_MFC;
	tuple->DesiredTuple = CISTPL_LONGLINK_MFC;
	if (pccard_get_next_tuple(s, function, tuple) == 0) {
	if (pccard_get_next_tuple(s, function, tuple) == 0) {
@@ -481,7 +469,7 @@ static int follow_link(struct pcmcia_socket *s, tuple_t *tuple)
    } else {
    } else {
	return -1;
	return -1;
    }
    }
    if (!(s->state & SOCKET_CARDBUS) && SPACE(tuple->Flags)) {
    if (SPACE(tuple->Flags)) {
	/* This is ugly, but a common CIS error is to code the long
	/* This is ugly, but a common CIS error is to code the long
	   link offset incorrectly, so we check the right spot... */
	   link offset incorrectly, so we check the right spot... */
	read_cis_cache(s, SPACE(tuple->Flags), ofs, 5, link);
	read_cis_cache(s, SPACE(tuple->Flags), ofs, 5, link);
@@ -507,7 +495,7 @@ int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int function, tuple_


    if (!s)
    if (!s)
	return -EINVAL;
	return -EINVAL;
    if (!(s->state & SOCKET_PRESENT))
    if (!(s->state & SOCKET_PRESENT) || (s->state & SOCKET_CARDBUS))
	return -ENODEV;
	return -ENODEV;


    link[1] = tuple->TupleLink;
    link[1] = tuple->TupleLink;
@@ -1192,119 +1180,6 @@ static int parse_cftable_entry(tuple_t *tuple,


/*====================================================================*/
/*====================================================================*/


#ifdef CONFIG_CARDBUS

static int parse_bar(tuple_t *tuple, cistpl_bar_t *bar)
{
    u_char *p;
    if (tuple->TupleDataLen < 6)
	return -EINVAL;
    p = (u_char *)tuple->TupleData;
    bar->attr = *p;
    p += 2;
    bar->size = get_unaligned_le32(p);
    return 0;
}

static int parse_config_cb(tuple_t *tuple, cistpl_config_t *config)
{
    u_char *p;

    p = (u_char *)tuple->TupleData;
    if ((*p != 3) || (tuple->TupleDataLen < 6))
	return -EINVAL;
    config->last_idx = *(++p);
    p++;
    config->base = get_unaligned_le32(p);
    config->subtuples = tuple->TupleDataLen - 6;
    return 0;
}

static int parse_cftable_entry_cb(tuple_t *tuple,
				  cistpl_cftable_entry_cb_t *entry)
{
    u_char *p, *q, features;

    p = tuple->TupleData;
    q = p + tuple->TupleDataLen;
    entry->index = *p & 0x3f;
    entry->flags = 0;
    if (*p & 0x40)
	entry->flags |= CISTPL_CFTABLE_DEFAULT;

    /* Process optional features */
    if (++p == q)
	    return -EINVAL;
    features = *p; p++;

    /* Power options */
    if ((features & 3) > 0) {
	p = parse_power(p, q, &entry->vcc);
	if (p == NULL)
		return -EINVAL;
    } else
	entry->vcc.present = 0;
    if ((features & 3) > 1) {
	p = parse_power(p, q, &entry->vpp1);
	if (p == NULL)
		return -EINVAL;
    } else
	entry->vpp1.present = 0;
    if ((features & 3) > 2) {
	p = parse_power(p, q, &entry->vpp2);
	if (p == NULL)
		return -EINVAL;
    } else
	entry->vpp2.present = 0;

    /* I/O window options */
    if (features & 0x08) {
	if (p == q)
		return -EINVAL;
	entry->io = *p; p++;
    } else
	entry->io = 0;

    /* Interrupt options */
    if (features & 0x10) {
	p = parse_irq(p, q, &entry->irq);
	if (p == NULL)
		return -EINVAL;
    } else
	entry->irq.IRQInfo1 = 0;

    if (features & 0x20) {
	if (p == q)
		return -EINVAL;
	entry->mem = *p; p++;
    } else
	entry->mem = 0;

    /* Misc features */
    if (features & 0x80) {
	if (p == q)
		return -EINVAL;
	entry->flags |= (*p << 8);
	if (*p & 0x80) {
	    if (++p == q)
		    return -EINVAL;
	    entry->flags |= (*p << 16);
	}
	while (*p & 0x80)
	    if (++p == q)
		    return -EINVAL;
	p++;
    }

    entry->subtuples = q-p;

    return 0;
}

#endif

/*====================================================================*/

static int parse_device_geo(tuple_t *tuple, cistpl_device_geo_t *geo)
static int parse_device_geo(tuple_t *tuple, cistpl_device_geo_t *geo)
{
{
    u_char *p, *q;
    u_char *p, *q;
@@ -1406,17 +1281,6 @@ int pcmcia_parse_tuple(tuple_t *tuple, cisparse_t *parse)
    case CISTPL_DEVICE_A:
    case CISTPL_DEVICE_A:
	ret = parse_device(tuple, &parse->device);
	ret = parse_device(tuple, &parse->device);
	break;
	break;
#ifdef CONFIG_CARDBUS
    case CISTPL_BAR:
	ret = parse_bar(tuple, &parse->bar);
	break;
    case CISTPL_CONFIG_CB:
	ret = parse_config_cb(tuple, &parse->config);
	break;
    case CISTPL_CFTABLE_ENTRY_CB:
	ret = parse_cftable_entry_cb(tuple, &parse->cftable_entry_cb);
	break;
#endif
    case CISTPL_CHECKSUM:
    case CISTPL_CHECKSUM:
	ret = parse_checksum(tuple, &parse->checksum);
	ret = parse_checksum(tuple, &parse->checksum);
	break;
	break;
+0 −6
Original line number Original line Diff line number Diff line
@@ -244,12 +244,6 @@ struct pcmcia_socket {
#endif /* CONFIG_PCMCIA_IOCTL */
#endif /* CONFIG_PCMCIA_IOCTL */
#endif /* CONFIG_PCMCIA */
#endif /* CONFIG_PCMCIA */


	/* cardbus (32-bit) */
#ifdef CONFIG_CARDBUS
	struct resource			*cb_cis_res;
	void __iomem			*cb_cis_virt;
#endif /* CONFIG_CARDBUS */

	/* socket device */
	/* socket device */
	struct device			dev;
	struct device			dev;
	/* data internal to the socket driver */
	/* data internal to the socket driver */