Skip to content

Commit

Permalink
[PATCH] pcmcia: request CIS via firmware interface
Browse files Browse the repository at this point in the history
Use the firmware method to load replacement CIS tables.  It is recommended
that the /lib/firmware/cis/ points to /etc/pcmcia/cis or the other way round
so that both old-style cardmgr and new-style hotplug/firmware can access these
"overwrite" files

Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
Dominik Brodowski authored and Linus Torvalds committed Jun 28, 2005
1 parent 90829cf commit daa9517
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 4 deletions.
14 changes: 14 additions & 0 deletions drivers/pcmcia/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,20 @@ config PCMCIA

If unsure, say Y.

config PCMCIA_LOAD_CIS
bool "Load CIS updates from userspace (EXPERIMENTAL)"
depends on PCMCIA && EXPERIMENTAL
select FW_LOADER
default y
help
Some PCMCIA cards require an updated Card Information Structure (CIS)
to be loaded from userspace to work correctly. If you say Y here,
and your userspace is arranged correctly, this will be loaded
automatically using the in-kernel firmware loader and the hotplug
subsystem, instead of relying on cardmgr from pcmcia-cs to do so.

If unsure, say Y.

config CARDBUS
bool "32-bit CardBus support"
depends on PCI
Expand Down
71 changes: 67 additions & 4 deletions drivers/pcmcia/ds.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include <linux/kref.h>
#include <linux/workqueue.h>
#include <linux/crc32.h>
#include <linux/firmware.h>

#include <asm/atomic.h>

Expand Down Expand Up @@ -295,6 +296,68 @@ static inline void pcmcia_check_driver(struct pcmcia_driver *p_drv) {
}
#endif


#ifdef CONFIG_PCMCIA_LOAD_CIS

/**
* pcmcia_load_firmware - load CIS from userspace if device-provided is broken
* @dev - the pcmcia device which needs a CIS override
* @filename - requested filename in /lib/firmware/cis/
*
* This uses the in-kernel firmware loading mechanism to use a "fake CIS" if
* the one provided by the card is broken. The firmware files reside in
* /lib/firmware/cis/ in userspace.
*/
static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)
{
struct pcmcia_socket *s = dev->socket;
const struct firmware *fw;
char path[20];
int ret=-ENOMEM;
cisdump_t *cis;

if (!filename)
return -EINVAL;

ds_dbg(1, "trying to load firmware %s\n", filename);

if (strlen(filename) > 14)
return -EINVAL;

snprintf(path, 20, "%s", filename);

if (request_firmware(&fw, path, &dev->dev) == 0) {
if (fw->size >= CISTPL_MAX_CIS_SIZE)
goto release;

cis = kmalloc(sizeof(cisdump_t), GFP_KERNEL);
if (!cis)
goto release;

memset(cis, 0, sizeof(cisdump_t));

cis->Length = fw->size + 1;
memcpy(cis->Data, fw->data, fw->size);

if (!pcmcia_replace_cis(s, cis))
ret = 0;
}
release:
release_firmware(fw);

return (ret);
}

#else /* !CONFIG_PCMCIA_LOAD_CIS */

static inline int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)
{
return -ENODEV;
}

#endif


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

static struct pcmcia_driver * get_pcmcia_driver (dev_info_t *dev_info);
Expand Down Expand Up @@ -739,11 +802,11 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev,
}

if (did->match_flags & PCMCIA_DEV_ID_MATCH_FAKE_CIS) {
if (!dev->socket->fake_cis) {
/* FIXME: evaluate using firmware helpers to
* automagically load it from userspace */
if (!dev->socket->fake_cis)
pcmcia_load_firmware(dev, did->cisfile);

if (!dev->socket->fake_cis)
return 0;
}
}

if (did->match_flags & PCMCIA_DEV_ID_MATCH_ANONYMOUS) {
Expand Down

0 comments on commit daa9517

Please sign in to comment.