Commit 39302175 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia-2.6/

* git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia-2.6/:
  [PATCH] pcmcia: fix deadlock in pcmcia_parse_events
  [PATCH] com20020_cs: more device support
  [PATCH] au1xxx: pcmcia: fix __init called from non-init
  [PATCH] kill open-coded offsetof in cm4000_cs.c ZERO_DEV()
  [PATCH] pcmcia: convert pcmcia_cs to kthread
  [PATCH] pcmcia: fix kernel-doc function name
  [PATCH] pcmcia: hostap_cs.c - 0xc00f,0x0000 conflicts with pcnet_cs
  [PATCH] pcmcia: at91_cf suspend/resume/wakeup
  [PATCH] pcmcia: Make ide_cs work with the memory space of CF-Cards if IO space is not available
  [PATCH] pcmcia: TI PCIxx12 CardBus controller support
  [PATCH] pcmcia: warn if driver requests exclusive, but gets a shared IRQ
  [PATCH] pcmcia: expose tool in pcmcia/Documentation/pcmcia/
  [PATCH] pcmcia: another ID for serial_cs.c
  [PATCH] yenta: fix hidden PCI bus numbers
  [PATCH] yenta: do power-up only after socket is configured
parents 1cfef5ed 4b7a89a3
/* crc32hash.c - derived from linux/lib/crc32.c, GNU GPL v2 */
/* Usage example:
$ ./crc32hash "Dual Speed"
*/
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
unsigned int crc32(unsigned char const *p, unsigned int len)
{
int i;
unsigned int crc = 0;
while (len--) {
crc ^= *p++;
for (i = 0; i < 8; i++)
crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0);
}
return crc;
}
int main(int argc, char **argv) {
unsigned int result;
if (argc != 2) {
printf("no string passed as argument\n");
return -1;
}
result = crc32(argv[1], strlen(argv[1]));
printf("0x%x\n", result);
return 0;
}
...@@ -27,37 +27,7 @@ pcmcia:m0149cC1ABf06pfn00fn00pa725B842DpbF1EFEE84pc0877B627pd00000000 ...@@ -27,37 +27,7 @@ pcmcia:m0149cC1ABf06pfn00fn00pa725B842DpbF1EFEE84pc0877B627pd00000000
The hex value after "pa" is the hash of product ID string 1, after "pb" for The hex value after "pa" is the hash of product ID string 1, after "pb" for
string 2 and so on. string 2 and so on.
Alternatively, you can use this small tool to determine the crc32 hash. Alternatively, you can use crc32hash (see Documentation/pcmcia/crc32hash.c)
simply pass the string you want to evaluate as argument to this program, to determine the crc32 hash. Simply pass the string you want to evaluate
e.g. as argument to this program, e.g.:
$ ./crc32hash "Dual Speed" $ ./crc32hash "Dual Speed"
-------------------------------------------------------------------------
/* crc32hash.c - derived from linux/lib/crc32.c, GNU GPL v2 */
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
unsigned int crc32(unsigned char const *p, unsigned int len)
{
int i;
unsigned int crc = 0;
while (len--) {
crc ^= *p++;
for (i = 0; i < 8; i++)
crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0);
}
return crc;
}
int main(int argc, char **argv) {
unsigned int result;
if (argc != 2) {
printf("no string passed as argument\n");
return -1;
}
result = crc32(argv[1], strlen(argv[1]));
printf("0x%x\n", result);
return 0;
}
...@@ -149,12 +149,7 @@ struct cm4000_dev { ...@@ -149,12 +149,7 @@ struct cm4000_dev {
#define ZERO_DEV(dev) \ #define ZERO_DEV(dev) \
memset(&dev->atr_csum,0, \ memset(&dev->atr_csum,0, \
sizeof(struct cm4000_dev) - \ sizeof(struct cm4000_dev) - \
/*link*/ sizeof(struct pcmcia_device *) - \ offsetof(struct cm4000_dev, atr_csum))
/*node*/ sizeof(dev_node_t) - \
/*atr*/ MAX_ATR*sizeof(char) - \
/*rbuf*/ 512*sizeof(char) - \
/*sbuf*/ 512*sizeof(char) - \
/*queue*/ 4*sizeof(wait_queue_head_t))
static struct pcmcia_device *dev_table[CM4000_MAX_DEV]; static struct pcmcia_device *dev_table[CM4000_MAX_DEV];
static struct class *cmm_class; static struct class *cmm_class;
......
...@@ -146,7 +146,16 @@ static void ide_detach(struct pcmcia_device *link) ...@@ -146,7 +146,16 @@ static void ide_detach(struct pcmcia_device *link)
kfree(link->priv); kfree(link->priv);
} /* ide_detach */ } /* ide_detach */
static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq, struct pcmcia_device *handle) static void idecs_mmio_fixup(ide_hwif_t *hwif)
{
default_hwif_mmiops(hwif);
hwif->mmio = 2;
ide_undecoded_slave(hwif);
}
static int idecs_register(unsigned long io, unsigned long ctl,
unsigned long irq, struct pcmcia_device *handle, int is_mmio)
{ {
hw_regs_t hw; hw_regs_t hw;
memset(&hw, 0, sizeof(hw)); memset(&hw, 0, sizeof(hw));
...@@ -154,7 +163,19 @@ static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq ...@@ -154,7 +163,19 @@ static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq
hw.irq = irq; hw.irq = irq;
hw.chipset = ide_pci; hw.chipset = ide_pci;
hw.dev = &handle->dev; hw.dev = &handle->dev;
return ide_register_hw_with_fixup(&hw, NULL, ide_undecoded_slave);
if(is_mmio)
return ide_register_hw_with_fixup(&hw, NULL, idecs_mmio_fixup);
else
return ide_register_hw_with_fixup(&hw, NULL, ide_undecoded_slave);
}
void outb_io(unsigned char value, unsigned long port) {
outb(value, port);
}
void outb_mem(unsigned char value, unsigned long port) {
writeb(value, (void __iomem *) port);
} }
/*====================================================================== /*======================================================================
...@@ -180,7 +201,8 @@ static int ide_config(struct pcmcia_device *link) ...@@ -180,7 +201,8 @@ static int ide_config(struct pcmcia_device *link)
} *stk = NULL; } *stk = NULL;
cistpl_cftable_entry_t *cfg; cistpl_cftable_entry_t *cfg;
int i, pass, last_ret = 0, last_fn = 0, hd, is_kme = 0; int i, pass, last_ret = 0, last_fn = 0, hd, is_kme = 0;
unsigned long io_base, ctl_base; unsigned long io_base, ctl_base, is_mmio, try_slave;
void (*my_outb)(unsigned char, unsigned long);
DEBUG(0, "ide_config(0x%p)\n", link); DEBUG(0, "ide_config(0x%p)\n", link);
...@@ -210,7 +232,7 @@ static int ide_config(struct pcmcia_device *link) ...@@ -210,7 +232,7 @@ static int ide_config(struct pcmcia_device *link)
/* Not sure if this is right... look up the current Vcc */ /* Not sure if this is right... look up the current Vcc */
CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &stk->conf)); CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &stk->conf));
pass = io_base = ctl_base = 0; pass = io_base = ctl_base = is_mmio = try_slave = 0;
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
tuple.Attributes = 0; tuple.Attributes = 0;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
...@@ -258,11 +280,45 @@ static int ide_config(struct pcmcia_device *link) ...@@ -258,11 +280,45 @@ static int ide_config(struct pcmcia_device *link)
goto next_entry; goto next_entry;
io_base = link->io.BasePort1; io_base = link->io.BasePort1;
ctl_base = link->io.BasePort1 + 0x0e; ctl_base = link->io.BasePort1 + 0x0e;
if (io->win[0].len >= 0x20)
try_slave = 1;
} else goto next_entry; } else goto next_entry;
/* If we've got this far, we're done */ /* If we've got this far, we're done */
break; break;
} }
if ((cfg->mem.nwin > 0) || (stk->dflt.mem.nwin > 0)) {
win_req_t req;
memreq_t map;
cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &stk->dflt.mem;
if (mem->win[0].len < 16)
goto next_entry;
req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
req.Attributes |= WIN_ENABLE;
req.Base = mem->win[0].host_addr;
req.Size = 0;
req.AccessSpeed = 0;
if (pcmcia_request_window(&link, &req, &link->win) != 0)
goto next_entry;
map.Page = 0; map.CardOffset = mem->win[0].card_addr;
if (pcmcia_map_mem_page(link->win, &map) != 0)
goto next_entry;
io_base = (unsigned long) ioremap(req.Base, req.Size);
ctl_base = io_base + 0x0e;
is_mmio = 1;
if (mem->win[0].len >= 0x20)
try_slave = 1;
break;
}
next_entry: next_entry:
if (cfg->flags & CISTPL_CFTABLE_DEFAULT) if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
memcpy(&stk->dflt, cfg, sizeof(stk->dflt)); memcpy(&stk->dflt, cfg, sizeof(stk->dflt));
...@@ -278,21 +334,26 @@ static int ide_config(struct pcmcia_device *link) ...@@ -278,21 +334,26 @@ static int ide_config(struct pcmcia_device *link)
CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
if(is_mmio)
my_outb = outb_mem;
else
my_outb = outb_io;
/* disable drive interrupts during IDE probe */ /* disable drive interrupts during IDE probe */
outb(0x02, ctl_base); my_outb(0x02, ctl_base);
/* special setup for KXLC005 card */ /* special setup for KXLC005 card */
if (is_kme) if (is_kme)
outb(0x81, ctl_base+1); my_outb(0x81, ctl_base+1);
/* retry registration in case device is still spinning up */ /* retry registration in case device is still spinning up */
for (hd = -1, i = 0; i < 10; i++) { for (hd = -1, i = 0; i < 10; i++) {
hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link); hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link, is_mmio);
if (hd >= 0) break; if (hd >= 0) break;
if (link->io.NumPorts1 == 0x20) { if (try_slave) {
outb(0x02, ctl_base + 0x10); my_outb(0x02, ctl_base + 0x10);
hd = idecs_register(io_base + 0x10, ctl_base + 0x10, hd = idecs_register(io_base + 0x10, ctl_base + 0x10,
link->irq.AssignedIRQ, link); link->irq.AssignedIRQ, link, is_mmio);
if (hd >= 0) { if (hd >= 0) {
io_base += 0x10; io_base += 0x10;
ctl_base += 0x10; ctl_base += 0x10;
......
...@@ -387,7 +387,10 @@ static int com20020_resume(struct pcmcia_device *link) ...@@ -387,7 +387,10 @@ static int com20020_resume(struct pcmcia_device *link)
} }
static struct pcmcia_device_id com20020_ids[] = { static struct pcmcia_device_id com20020_ids[] = {
PCMCIA_DEVICE_PROD_ID12("Contemporary Control Systems, Inc.", "PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf), PCMCIA_DEVICE_PROD_ID12("Contemporary Control Systems, Inc.",
"PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf),
PCMCIA_DEVICE_PROD_ID12("SoHard AG",
"SH ARC PCMCIA", 0xf8991729, 0x69dff0c7),
PCMCIA_DEVICE_NULL PCMCIA_DEVICE_NULL
}; };
MODULE_DEVICE_TABLE(pcmcia, com20020_ids); MODULE_DEVICE_TABLE(pcmcia, com20020_ids);
......
...@@ -844,7 +844,7 @@ static struct pcmcia_device_id hostap_cs_ids[] = { ...@@ -844,7 +844,7 @@ static struct pcmcia_device_id hostap_cs_ids[] = {
PCMCIA_DEVICE_MANF_CARD(0x02d2, 0x0001), PCMCIA_DEVICE_MANF_CARD(0x02d2, 0x0001),
PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x0001), PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x0001),
PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300), PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300),
PCMCIA_DEVICE_MANF_CARD(0xc00f, 0x0000), /* PCMCIA_DEVICE_MANF_CARD(0xc00f, 0x0000), conflict with pcnet_cs */
PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002),
PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005),
PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0010), PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0010),
......
...@@ -214,11 +214,10 @@ static struct pccard_operations at91_cf_ops = { ...@@ -214,11 +214,10 @@ static struct pccard_operations at91_cf_ops = {
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
static int __init at91_cf_probe(struct device *dev) static int __init at91_cf_probe(struct platform_device *pdev)
{ {
struct at91_cf_socket *cf; struct at91_cf_socket *cf;
struct at91_cf_data *board = dev->platform_data; struct at91_cf_data *board = pdev->dev.platform_data;
struct platform_device *pdev = to_platform_device(dev);
struct resource *io; struct resource *io;
unsigned int csa; unsigned int csa;
int status; int status;
...@@ -236,7 +235,7 @@ static int __init at91_cf_probe(struct device *dev) ...@@ -236,7 +235,7 @@ static int __init at91_cf_probe(struct device *dev)
cf->board = board; cf->board = board;
cf->pdev = pdev; cf->pdev = pdev;
dev_set_drvdata(dev, cf); platform_set_drvdata(pdev, cf);
/* CF takes over CS4, CS5, CS6 */ /* CF takes over CS4, CS5, CS6 */
csa = at91_sys_read(AT91_EBI_CSA); csa = at91_sys_read(AT91_EBI_CSA);
...@@ -271,6 +270,7 @@ static int __init at91_cf_probe(struct device *dev) ...@@ -271,6 +270,7 @@ static int __init at91_cf_probe(struct device *dev)
SA_SAMPLE_RANDOM, driver_name, cf); SA_SAMPLE_RANDOM, driver_name, cf);
if (status < 0) if (status < 0)
goto fail0; goto fail0;
device_init_wakeup(&pdev->dev, 1);
/* /*
* The card driver will request this irq later as needed. * The card driver will request this irq later as needed.
...@@ -301,7 +301,7 @@ static int __init at91_cf_probe(struct device *dev) ...@@ -301,7 +301,7 @@ static int __init at91_cf_probe(struct device *dev)
board->det_pin, board->irq_pin); board->det_pin, board->irq_pin);
cf->socket.owner = THIS_MODULE; cf->socket.owner = THIS_MODULE;
cf->socket.dev.dev = dev; cf->socket.dev.dev = &pdev->dev;
cf->socket.ops = &at91_cf_ops; cf->socket.ops = &at91_cf_ops;
cf->socket.resource_ops = &pccard_static_ops; cf->socket.resource_ops = &pccard_static_ops;
cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP
...@@ -323,21 +323,25 @@ static int __init at91_cf_probe(struct device *dev) ...@@ -323,21 +323,25 @@ static int __init at91_cf_probe(struct device *dev)
free_irq(board->irq_pin, cf); free_irq(board->irq_pin, cf);
fail0a: fail0a:
free_irq(board->det_pin, cf); free_irq(board->det_pin, cf);
device_init_wakeup(&pdev->dev, 0);
fail0: fail0:
at91_sys_write(AT91_EBI_CSA, csa); at91_sys_write(AT91_EBI_CSA, csa);
kfree(cf); kfree(cf);
return status; return status;
} }
static int __exit at91_cf_remove(struct device *dev) static int __exit at91_cf_remove(struct platform_device *pdev)
{ {
struct at91_cf_socket *cf = dev_get_drvdata(dev); struct at91_cf_socket *cf = platform_get_drvdata(pdev);
struct at91_cf_data *board = cf->board;
struct resource *io = cf->socket.io[0].res; struct resource *io = cf->socket.io[0].res;
unsigned int csa; unsigned int csa;
pcmcia_unregister_socket(&cf->socket); pcmcia_unregister_socket(&cf->socket);
free_irq(cf->board->irq_pin, cf); if (board->irq_pin)
free_irq(cf->board->det_pin, cf); free_irq(board->irq_pin, cf);
free_irq(board->det_pin, cf);
device_init_wakeup(&pdev->dev, 0);
iounmap((void __iomem *) cf->socket.io_offset); iounmap((void __iomem *) cf->socket.io_offset);
release_mem_region(io->start, io->end + 1 - io->start); release_mem_region(io->start, io->end + 1 - io->start);
...@@ -348,26 +352,65 @@ static int __exit at91_cf_remove(struct device *dev) ...@@ -348,26 +352,65 @@ static int __exit at91_cf_remove(struct device *dev)
return 0; return 0;
} }
static struct device_driver at91_cf_driver = { #ifdef CONFIG_PM
.name = (char *) driver_name,
.bus = &platform_bus_type, static int at91_cf_suspend(struct platform_device *pdev, pm_message_t mesg)
{
struct at91_cf_socket *cf = platform_get_drvdata(pdev);
struct at91_cf_data *board = cf->board;
pcmcia_socket_dev_suspend(&pdev->dev, mesg);
if (device_may_wakeup(&pdev->dev))
enable_irq_wake(board->det_pin);
else {
disable_irq_wake(board->det_pin);
disable_irq(board->det_pin);
}
if (board->irq_pin)
disable_irq(board->irq_pin);
return 0;
}
static int at91_cf_resume(struct platform_device *pdev)
{
struct at91_cf_socket *cf = platform_get_drvdata(pdev);
struct at91_cf_data *board = cf->board;
if (board->irq_pin)
enable_irq(board->irq_pin);
if (!device_may_wakeup(&pdev->dev))
enable_irq(board->det_pin);
pcmcia_socket_dev_resume(&pdev->dev);
return 0;
}
#else
#define at91_cf_suspend NULL
#define at91_cf_resume NULL
#endif
static struct platform_driver at91_cf_driver = {
.driver = {
.name = (char *) driver_name,
.owner = THIS_MODULE,
},
.probe = at91_cf_probe, .probe = at91_cf_probe,
.remove = __exit_p(at91_cf_remove), .remove = __exit_p(at91_cf_remove),
.suspend = pcmcia_socket_dev_suspend, .suspend = at91_cf_suspend,
.resume = pcmcia_socket_dev_resume, .resume = at91_cf_resume,
}; };
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
static int __init at91_cf_init(void) static int __init at91_cf_init(void)
{ {
return driver_register(&at91_cf_driver); return platform_driver_register(&at91_cf_driver);
} }
module_init(at91_cf_init); module_init(at91_cf_init);
static void __exit at91_cf_exit(void) static void __exit at91_cf_exit(void)
{ {
driver_unregister(&at91_cf_driver); platform_driver_unregister(&at91_cf_driver);
} }
module_exit(at91_cf_exit); module_exit(at91_cf_exit);
......
...@@ -296,7 +296,7 @@ struct pcmcia_low_level db1x00_pcmcia_ops = { ...@@ -296,7 +296,7 @@ struct pcmcia_low_level db1x00_pcmcia_ops = {
.socket_suspend = db1x00_socket_suspend .socket_suspend = db1x00_socket_suspend
}; };
int __init au1x_board_init(struct device *dev) int au1x_board_init(struct device *dev)
{ {
int ret = -ENODEV; int ret = -ENODEV;
bcsr->pcmcia = 0; /* turn off power, if it's not already off */ bcsr->pcmcia = 0; /* turn off power, if it's not already off */
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/kthread.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/irq.h> #include <asm/irq.h>
...@@ -176,6 +177,7 @@ static int pccardd(void *__skt); ...@@ -176,6 +177,7 @@ static int pccardd(void *__skt);
*/ */
int pcmcia_register_socket(struct pcmcia_socket *socket) int pcmcia_register_socket(struct pcmcia_socket *socket)
{ {
struct task_struct *tsk;
int ret; int ret;
if (!socket || !socket->ops || !socket->dev.dev || !socket->resource_ops) if (!socket || !socket->ops || !socket->dev.dev || !socket->resource_ops)
...@@ -239,15 +241,18 @@ int pcmcia_register_socket(struct pcmcia_socket *socket) ...@@ -239,15 +241,18 @@ int pcmcia_register_socket(struct pcmcia_socket *socket)
mutex_init(&socket->skt_mutex); mutex_init(&socket->skt_mutex);
spin_lock_init(&socket->thread_lock); spin_lock_init(&socket->thread_lock);
ret = kernel_thread(pccardd, socket, CLONE_KERNEL); tsk = kthread_run(pccardd, socket, "pccardd");
if (ret < 0) if (IS_ERR(tsk)) {
ret = PTR_ERR(tsk);
goto err; goto err;
}
wait_for_completion(&socket->thread_done); wait_for_completion(&socket->thread_done);
if(!socket->thread) { if (!socket->thread) {
printk(KERN_WARNING "PCMCIA: warning: socket thread for socket %p did not start\n", socket); printk(KERN_WARNING "PCMCIA: warning: socket thread for socket %p did not start\n", socket);
return -EIO; return -EIO;
} }
pcmcia_parse_events(socket, SS_DETECT); pcmcia_parse_events(socket, SS_DETECT);
return 0; return 0;
...@@ -272,10 +277,8 @@ void pcmcia_unregister_socket(struct pcmcia_socket *socket) ...@@ -272,10 +277,8 @@ void pcmcia_unregister_socket(struct pcmcia_socket *socket)
cs_dbg(socket, 0, "pcmcia_unregister_socket(0x%p)\n", socket->ops); cs_dbg(socket, 0, "pcmcia_unregister_socket(0x%p)\n", socket->ops);
if (socket->thread) { if (socket->thread) {
init_completion(&socket->thread_done);
socket->thread = NULL;
wake_up(&socket->thread_wait); wake_up(&socket->thread_wait);
wait_for_completion(&socket->thread_done); kthread_stop(socket->thread);
} }
release_cis_mem(socket); release_cis_mem(socket);
...@@ -630,8 +633,6 @@ static int pccardd(void *__skt) ...@@ -630,8 +633,6 @@ static int pccardd(void *__skt)
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
int ret; int ret;
daemonize("pccardd");
skt->thread = current; skt->thread = current;
skt->socket = dead_socket; skt->socket = dead_socket;
skt->ops->init(skt); skt->ops->init(skt);
...@@ -643,7 +644,8 @@ static int pccardd(void *__skt) ...@@ -643,7 +644,8 @@ static int pccardd(void *__skt)
printk(KERN_WARNING "PCMCIA: unable to register socket 0x%p\n", printk(KERN_WARNING "PCMCIA: unable to register socket 0x%p\n",
skt); skt);
skt->thread = NULL; skt->thread = NULL;
complete_and_exit(&skt->thread_done, 0); complete(&skt->thread_done);
return 0;
} }
add_wait_queue(&skt->thread_wait, &wait); add_wait_queue(&skt->thread_wait, &wait);
...@@ -674,7 +676,7 @@ static int pccardd(void *__skt) ...@@ -674,7 +676,7 @@ static int pccardd(void *__skt)
continue; continue;
} }
if (!skt->thread) if (kthread_should_stop())
break; break;
schedule(); schedule();
...@@ -688,7 +690,7 @@ static int pccardd(void *__skt) ...@@ -688,7 +690,7 @@ static int pccardd(void *__skt)
/* remove from the device core */ /* remove from the device core */
class_device_unregister(&skt->dev); class_device_unregister(&skt->dev);
complete_and_exit(&skt->thread_done, 0); return 0;
} }
/* /*
...@@ -697,11 +699,12 @@ static int pccardd(void *__skt) ...@@ -697,11 +699,12 @@ static int pccardd(void *__skt)
*/ */
void pcmcia_parse_events(struct pcmcia_socket *s, u_int events) void pcmcia_parse_events(struct pcmcia_socket *s, u_int events)
{ {
unsigned long flags;
cs_dbg(s, 4, "parse_events: events %08x\n", events); cs_dbg(s, 4, "parse_events: events %08x\n", events);
if (s->thread) { if (s->thread) {
spin_lock(&s->thread_lock); spin_lock_irqsave(&s->thread_lock, flags);
s->thread_events |= events; s->thread_events |= events;
spin_unlock(&s->thread_lock); spin_unlock_irqrestore(&s->thread_lock, flags);
wake_up(&s->thread_wait); wake_up(&s->thread_wait);
} }
......
...@@ -788,6 +788,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) ...@@ -788,6 +788,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
struct pcmcia_socket *s = p_dev->socket; struct pcmcia_socket *s = p_dev->socket;
config_t *c; config_t *c;
int ret = CS_IN_USE, irq = 0; int ret = CS_IN_USE, irq = 0;
int type;
if (!(s->state & SOCKET_PRESENT)) if (!(s->state & SOCKET_PRESENT))
return CS_NO_CARD; return CS_NO_CARD;
...@@ -797,6 +798,13 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) ...@@ -797,6 +798,13 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
if (c->state & CONFIG_IRQ_REQ) if (c->state & CONFIG_IRQ_REQ)
return CS_IN_USE; return CS_IN_USE;
/* Decide what type of interrupt we are registering */
type = 0;
if (s->functions > 1) /* All of this ought to be handled higher up */
type = SA_SHIRQ;
if (req->Attributes & IRQ_TYPE_DYNAMIC_SHARING)
type = SA_SHIRQ;
#ifdef CONFIG_PCMCIA_PROBE #ifdef CONFIG_PCMCIA_PROBE
if (s->irq.AssignedIRQ != 0) { if (s->irq.AssignedIRQ != 0) {
/* If the interrupt is already assigned, it must be the same */ /* If the interrupt is already assigned, it must be the same */
...@@ -822,9 +830,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) ...@@ -822,9 +830,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
* marked as used by the kernel resource management core */ * marked as used by the kernel resource management core */
ret = request_irq(irq, ret = request_irq(irq,
(req->Attributes & IRQ_HANDLE_PRESENT) ? req->Handler : test_action, (req->Attributes & IRQ_HANDLE_PRESENT) ? req->Handler : test_action,
((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) || type,
(s->functions > 1) ||
(irq == s->pci_irq)) ? SA_SHIRQ : 0,
p_dev->devname, p_dev->devname,
(req->Attributes & IRQ_HANDLE_PRESENT) ? req->Instance : data); (req->Attributes & IRQ_HANDLE_PRESENT) ? req->Instance : data);
if (!ret) { if (!ret) {
...@@ -839,18 +845,21 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) ...@@ -839,18 +845,21 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
if (ret && !s->irq.AssignedIRQ) { if (ret && !s->irq.AssignedIRQ) {
if (!s->pci_irq) if (!s->pci_irq)
return ret; return ret;
type = SA_SHIRQ;
irq = s->pci_irq; irq = s->pci_irq;
} }
if (ret && req->Attributes & IRQ_HANDLE_PRESENT) { if (ret && (req->Attributes & IRQ_HANDLE_PRESENT)) {
if (request_irq(irq, req->Handler, if (request_irq(irq, req->Handler, type, p_dev->devname, req->Instance))
((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) ||
(s->functions > 1) ||
(irq == s->pci_irq)) ? SA_SHIRQ : 0,
p_dev->devname, req->Instance))
return CS_IN_USE; return CS_IN_USE;
} }
/* Make sure the fact the request type was overridden is passed back */
if (type == SA_SHIRQ && !(req->Attributes & IRQ_TYPE_DYNAMIC_SHARING)) {
req->Attributes |= IRQ_TYPE_DYNAMIC_SHARING;
printk(KERN_WARNING "pcmcia: request for exclusive IRQ could not be fulfilled.\n");
printk(KERN_WARNING "pcmcia: the driver needs updating to supported shared IRQ lines.\n");
}
c->irq.Attributes = req->Attributes; c->irq.Attributes = req->Attributes;
s->irq.AssignedIRQ = req->AssignedIRQ = irq; s->irq.AssignedIRQ = req->AssignedIRQ = irq;
s->irq.Config++; s->irq.Config++;
......
...@@ -647,6 +647,7 @@ static int ti12xx_2nd_slot_empty(struct yenta_socket *socket) ...@@ -647,6 +647,7 @@ static int ti12xx_2nd_slot_empty(struct yenta_socket *socket)
*/ */
break; break;
case PCI_DEVICE_ID_TI_XX12:
case PCI_DEVICE_ID_TI_X515: case PCI_DEVICE_ID_TI_X515:
case PCI_DEVICE_ID_TI_X420: case PCI_DEVICE_ID_TI_X420:
case PCI_DEVICE_ID_TI_X620: case PCI_DEVICE_ID_TI_X620:
......
...@@ -287,7 +287,10 @@ static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state) ...@@ -287,7 +287,10 @@ static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
u16 bridge; u16 bridge;
yenta_set_power(socket, state); /* if powering down: do it immediately */
if (state->Vcc == 0)
yenta_set_power(socket, state);
socket->io_irq = state->io_irq; socket->io_irq = state->io_irq;
bridge = config_readw(socket, CB_BRIDGE_CONTROL) & ~(CB_BRIDGE_CRST | CB_BRIDGE_INTR); bridge = config_readw(socket, CB_BRIDGE_CONTROL) & ~(CB_BRIDGE_CRST | CB_BRIDGE_INTR);
if (cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) { if (cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) {
...@@ -339,6 +342,10 @@ static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state) ...@@ -339,6 +342,10 @@ static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
/* Socket event mask: get card insert/remove events.. */ /* Socket event mask: get card insert/remove events.. */
cb_writel(socket, CB_SOCKET_EVENT, -1); cb_writel(socket, CB_SOCKET_EVENT, -1);
cb_writel(socket, CB_SOCKET_MASK, CB_CDMASK); cb_writel(socket, CB_SOCKET_MASK, CB_CDMASK);
/* if powering up: do it as the last step when the socket is configured */
if (state->Vcc != 0)
yenta_set_power(socket, state);
return 0; return 0;
} }
...@@ -998,6 +1005,77 @@ static void yenta_config_init(struct yenta_socket *socket) ...@@ -998,6 +1005,77 @@ static void yenta_config_init(struct yenta_socket *socket)
config_writew(socket, CB_BRIDGE_CONTROL, bridge); config_writew(socket, CB_BRIDGE_CONTROL, bridge);
} }
/**
* yenta_fixup_parent_bridge - Fix subordinate bus# of the parent bridge
* @cardbus_bridge: The PCI bus which the CardBus bridge bridges to
*
* Checks if devices on the bus which the CardBus bridge bridges to would be
* invisible during PCI scans because of a misconfigured subordinate number
* of the parent brige - some BIOSes seem to be too lazy to set it right.
* Does the fixup carefully by checking how far it can go without conflicts.
* See http://bugzilla.kernel.org/show_bug.cgi?id=2944 for more information.
*/
static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge)
{
struct list_head *tmp;
unsigned char upper_limit;
/*
* We only check and fix the parent bridge: All systems which need
* this fixup that have been reviewed are laptops and the only bridge
* which needed fixing was the parent bridge of the CardBus bridge:
*/
struct pci_bus *bridge_to_fix = cardbus_bridge->parent;
/* Check bus numbers are already set up correctly: */
if (bridge_to_fix->subordinate >= cardbus_bridge->subordinate)
return; /* The subordinate number is ok, nothing to do */
if (!bridge_to_fix->parent)
return; /* Root bridges are ok */
/* stay within the limits of the bus range of the parent: */
upper_limit = bridge_to_fix->parent->subordinate;
/* check the bus ranges of all silbling bridges to prevent overlap */
list_for_each(tmp, &bridge_to_fix->parent->children) {
struct pci_bus * silbling = pci_bus_b(tmp);
/*
* If the silbling has a higher secondary bus number
* and it's secondary is equal or smaller than our
* current upper limit, set the new upper limit to
* the bus number below the silbling's range:
*/
if (silbling->secondary > bridge_to_fix->subordinate
&& silbling->secondary <= upper_limit)
upper_limit = silbling->secondary - 1;
}
/* Show that the wanted subordinate number is not possible: */
if (cardbus_bridge->subordinate > upper_limit)
printk(KERN_WARNING "Yenta: Upper limit for fixing this "
"bridge's parent bridge: #%02x\n", upper_limit);
/* If we have room to increase the bridge's subordinate number, */
if (bridge_to_fix->subordinate < upper_limit) {
/* use the highest number of the hidden bus, within limits */
unsigned char subordinate_to_assign =
min(cardbus_bridge->subordinate, upper_limit);
printk(KERN_INFO "Yenta: Raising subordinate bus# of parent "
"bus (#%02x) from #%02x to #%02x\n",
bridge_to_fix->number,
bridge_to_fix->subordinate, subordinate_to_assign);
/* Save the new subordinate in the bus struct of the bridge */
bridge_to_fix->subordinate = subordinate_to_assign;
/* and update the PCI config space with the new subordinate */
pci_write_config_byte(bridge_to_fix->self,
PCI_SUBORDINATE_BUS, bridge_to_fix->subordinate);
}
}
/* /*
* Initialize a cardbus controller. Make sure we have a usable * Initialize a cardbus controller. Make sure we have a usable
* interrupt, and that we can map the cardbus area. Fill in the * interrupt, and that we can map the cardbus area. Fill in the
...@@ -1113,6 +1191,8 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i ...@@ -1113,6 +1191,8 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
yenta_get_socket_capabilities(socket, isa_interrupts); yenta_get_socket_capabilities(socket, isa_interrupts);
printk(KERN_INFO "Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE)); printk(KERN_INFO "Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE));
yenta_fixup_parent_bridge(dev->subordinate);
/* Register it with the pcmcia layer.. */ /* Register it with the pcmcia layer.. */
ret = pcmcia_register_socket(&socket->socket); ret = pcmcia_register_socket(&socket->socket);
if (ret == 0) { if (ret == 0) {
...@@ -1232,6 +1312,7 @@ static struct pci_device_id yenta_table [] = { ...@@ -1232,6 +1312,7 @@ static struct pci_device_id yenta_table [] = {
CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX21_XX11, TI12XX), CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX21_XX11, TI12XX),
CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X515, TI12XX), CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X515, TI12XX),
CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX12, TI12XX),
CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X420, TI12XX), CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X420, TI12XX),
CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X620, TI12XX), CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X620, TI12XX),
CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7410, TI12XX), CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7410, TI12XX),
......
...@@ -786,6 +786,7 @@ static struct pcmcia_device_id serial_ids[] = { ...@@ -786,6 +786,7 @@ static struct pcmcia_device_id serial_ids[] = {
PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "COMpad4.cis"), PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "COMpad4.cis"),
PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "COMpad2.cis"), PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "COMpad2.cis"),
PCMCIA_DEVICE_CIS_PROD_ID2("RS-COM 2P", 0xad20b156, "RS-COM-2P.cis"), PCMCIA_DEVICE_CIS_PROD_ID2("RS-COM 2P", 0xad20b156, "RS-COM-2P.cis"),
PCMCIA_DEVICE_CIS_MANF_CARD(0x0013, 0x0000, "GLOBETROTTER.cis"),
/* too generic */ /* too generic */
/* PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0160, 0x0002), */ /* PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0160, 0x0002), */
/* PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0160, 0x0002), */ /* PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0160, 0x0002), */
......
...@@ -729,6 +729,7 @@ ...@@ -729,6 +729,7 @@
#define PCI_DEVICE_ID_TI_4450 0x8011 #define PCI_DEVICE_ID_TI_4450 0x8011
#define PCI_DEVICE_ID_TI_XX21_XX11 0x8031 #define PCI_DEVICE_ID_TI_XX21_XX11 0x8031
#define PCI_DEVICE_ID_TI_X515 0x8036 #define PCI_DEVICE_ID_TI_X515 0x8036
#define PCI_DEVICE_ID_TI_XX12 0x8039
#define PCI_DEVICE_ID_TI_1130 0xac12 #define PCI_DEVICE_ID_TI_1130 0xac12
#define PCI_DEVICE_ID_TI_1031 0xac13 #define PCI_DEVICE_ID_TI_1031 0xac13
#define PCI_DEVICE_ID_TI_1131 0xac15 #define PCI_DEVICE_ID_TI_1131 0xac15
......
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