Commit 27ee8963 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia-2.6

* 'urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia-2.6:
  pcmcia: fix error handling in cm4000_cs.c
  drivers/pcmcia: Add missing local_irq_restore
  serial_cs: MD55x support (PCMCIA GPRS/EDGE modem) (kernel 2.6.33)
  pcmcia: avoid late calls to pccard_validate_cis
  pcmcia: fix ioport size calculation in rsrc_nonstatic
  pcmcia: re-start on MFC override
  pcmcia: fix io_probe due to parent (PCI) resources
  pcmcia: use previously assigned IRQ for all card functions
parents ac8bf564 07a71415
...@@ -1026,14 +1026,16 @@ static ssize_t cmm_read(struct file *filp, __user char *buf, size_t count, ...@@ -1026,14 +1026,16 @@ static ssize_t cmm_read(struct file *filp, __user char *buf, size_t count,
xoutb(0, REG_FLAGS1(iobase)); /* clear detectCMM */ xoutb(0, REG_FLAGS1(iobase)); /* clear detectCMM */
/* last check before exit */ /* last check before exit */
if (!io_detect_cm4000(iobase, dev)) if (!io_detect_cm4000(iobase, dev)) {
count = -ENODEV; rc = -ENODEV;
goto release_io;
}
if (test_bit(IS_INVREV, &dev->flags) && count > 0) if (test_bit(IS_INVREV, &dev->flags) && count > 0)
str_invert_revert(dev->rbuf, count); str_invert_revert(dev->rbuf, count);
if (copy_to_user(buf, dev->rbuf, count)) if (copy_to_user(buf, dev->rbuf, count))
return -EFAULT; rc = -EFAULT;
release_io: release_io:
clear_bit(LOCK_IO, &dev->flags); clear_bit(LOCK_IO, &dev->flags);
......
...@@ -1484,6 +1484,11 @@ int pccard_validate_cis(struct pcmcia_socket *s, unsigned int *info) ...@@ -1484,6 +1484,11 @@ int pccard_validate_cis(struct pcmcia_socket *s, unsigned int *info)
if (!s) if (!s)
return -EINVAL; return -EINVAL;
if (s->functions) {
WARN_ON(1);
return -EINVAL;
}
/* We do not want to validate the CIS cache... */ /* We do not want to validate the CIS cache... */
mutex_lock(&s->ops_mutex); mutex_lock(&s->ops_mutex);
destroy_cis_cache(s); destroy_cis_cache(s);
...@@ -1639,7 +1644,7 @@ static ssize_t pccard_show_cis(struct kobject *kobj, ...@@ -1639,7 +1644,7 @@ static ssize_t pccard_show_cis(struct kobject *kobj,
count = 0; count = 0;
else { else {
struct pcmcia_socket *s; struct pcmcia_socket *s;
unsigned int chains; unsigned int chains = 1;
if (off + count > size) if (off + count > size)
count = size - off; count = size - off;
...@@ -1648,7 +1653,7 @@ static ssize_t pccard_show_cis(struct kobject *kobj, ...@@ -1648,7 +1653,7 @@ static ssize_t pccard_show_cis(struct kobject *kobj,
if (!(s->state & SOCKET_PRESENT)) if (!(s->state & SOCKET_PRESENT))
return -ENODEV; return -ENODEV;
if (pccard_validate_cis(s, &chains)) if (!s->functions && pccard_validate_cis(s, &chains))
return -EIO; return -EIO;
if (!chains) if (!chains)
return -ENODATA; return -ENODATA;
......
...@@ -166,8 +166,10 @@ static int db1x_pcmcia_setup_irqs(struct db1x_pcmcia_sock *sock) ...@@ -166,8 +166,10 @@ static int db1x_pcmcia_setup_irqs(struct db1x_pcmcia_sock *sock)
ret = request_irq(sock->insert_irq, db1200_pcmcia_cdirq, ret = request_irq(sock->insert_irq, db1200_pcmcia_cdirq,
IRQF_DISABLED, "pcmcia_insert", sock); IRQF_DISABLED, "pcmcia_insert", sock);
if (ret) if (ret) {
local_irq_restore(flags);
goto out1; goto out1;
}
ret = request_irq(sock->eject_irq, db1200_pcmcia_cdirq, ret = request_irq(sock->eject_irq, db1200_pcmcia_cdirq,
IRQF_DISABLED, "pcmcia_eject", sock); IRQF_DISABLED, "pcmcia_eject", sock);
......
...@@ -687,12 +687,10 @@ static void pcmcia_requery(struct pcmcia_socket *s) ...@@ -687,12 +687,10 @@ static void pcmcia_requery(struct pcmcia_socket *s)
new_funcs = mfc.nfn; new_funcs = mfc.nfn;
else else
new_funcs = 1; new_funcs = 1;
if (old_funcs > new_funcs) { if (old_funcs != new_funcs) {
/* we need to re-start */
pcmcia_card_remove(s, NULL); pcmcia_card_remove(s, NULL);
pcmcia_card_add(s); pcmcia_card_add(s);
} else if (new_funcs > old_funcs) {
s->functions = new_funcs;
pcmcia_device_add(s, 1);
} }
} }
...@@ -728,6 +726,8 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename) ...@@ -728,6 +726,8 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)
struct pcmcia_socket *s = dev->socket; struct pcmcia_socket *s = dev->socket;
const struct firmware *fw; const struct firmware *fw;
int ret = -ENOMEM; int ret = -ENOMEM;
cistpl_longlink_mfc_t mfc;
int old_funcs, new_funcs = 1;
if (!filename) if (!filename)
return -EINVAL; return -EINVAL;
...@@ -750,6 +750,14 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename) ...@@ -750,6 +750,14 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)
goto release; goto release;
} }
/* we need to re-start if the number of functions changed */
old_funcs = s->functions;
if (!pccard_read_tuple(s, BIND_FN_ALL, CISTPL_LONGLINK_MFC,
&mfc))
new_funcs = mfc.nfn;
if (old_funcs != new_funcs)
ret = -EBUSY;
/* update information */ /* update information */
pcmcia_device_query(dev); pcmcia_device_query(dev);
...@@ -858,9 +866,7 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev, ...@@ -858,9 +866,7 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev,
if (did->match_flags & PCMCIA_DEV_ID_MATCH_FAKE_CIS) { if (did->match_flags & PCMCIA_DEV_ID_MATCH_FAKE_CIS) {
dev_dbg(&dev->dev, "device needs a fake CIS\n"); dev_dbg(&dev->dev, "device needs a fake CIS\n");
if (!dev->socket->fake_cis) if (!dev->socket->fake_cis)
pcmcia_load_firmware(dev, did->cisfile); if (pcmcia_load_firmware(dev, did->cisfile))
if (!dev->socket->fake_cis)
return 0; return 0;
} }
......
...@@ -755,12 +755,12 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) ...@@ -755,12 +755,12 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
else else
printk(KERN_WARNING "pcmcia: Driver needs updating to support IRQ sharing.\n"); printk(KERN_WARNING "pcmcia: Driver needs updating to support IRQ sharing.\n");
#ifdef CONFIG_PCMCIA_PROBE
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 */
if (s->irq.AssignedIRQ != 0)
irq = s->irq.AssignedIRQ; irq = s->irq.AssignedIRQ;
} else {
#ifdef CONFIG_PCMCIA_PROBE
if (!irq) {
int try; int try;
u32 mask = s->irq_mask; u32 mask = s->irq_mask;
void *data = p_dev; /* something unique to this device */ void *data = p_dev; /* something unique to this device */
......
...@@ -214,7 +214,7 @@ static void do_io_probe(struct pcmcia_socket *s, unsigned int base, ...@@ -214,7 +214,7 @@ static void do_io_probe(struct pcmcia_socket *s, unsigned int base,
return; return;
} }
for (i = base, most = 0; i < base+num; i += 8) { for (i = base, most = 0; i < base+num; i += 8) {
res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA ioprobe"); res = claim_region(s, i, 8, IORESOURCE_IO, "PCMCIA ioprobe");
if (!res) if (!res)
continue; continue;
hole = inb(i); hole = inb(i);
...@@ -231,9 +231,14 @@ static void do_io_probe(struct pcmcia_socket *s, unsigned int base, ...@@ -231,9 +231,14 @@ static void do_io_probe(struct pcmcia_socket *s, unsigned int base,
bad = any = 0; bad = any = 0;
for (i = base; i < base+num; i += 8) { for (i = base; i < base+num; i += 8) {
res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA ioprobe"); res = claim_region(s, i, 8, IORESOURCE_IO, "PCMCIA ioprobe");
if (!res) if (!res) {
if (!any)
printk(" excluding");
if (!bad)
bad = any = i;
continue; continue;
}
for (j = 0; j < 8; j++) for (j = 0; j < 8; j++)
if (inb(i+j) != most) if (inb(i+j) != most)
break; break;
...@@ -253,6 +258,7 @@ static void do_io_probe(struct pcmcia_socket *s, unsigned int base, ...@@ -253,6 +258,7 @@ static void do_io_probe(struct pcmcia_socket *s, unsigned int base,
} }
if (bad) { if (bad) {
if ((num > 16) && (bad == base) && (i == base+num)) { if ((num > 16) && (bad == base) && (i == base+num)) {
sub_interval(&s_data->io_db, bad, i-bad);
printk(" nothing: probe failed.\n"); printk(" nothing: probe failed.\n");
return; return;
} else { } else {
...@@ -804,7 +810,7 @@ static int adjust_memory(struct pcmcia_socket *s, unsigned int action, unsigned ...@@ -804,7 +810,7 @@ static int adjust_memory(struct pcmcia_socket *s, unsigned int action, unsigned
static int adjust_io(struct pcmcia_socket *s, unsigned int action, unsigned long start, unsigned long end) static int adjust_io(struct pcmcia_socket *s, unsigned int action, unsigned long start, unsigned long end)
{ {
struct socket_data *data = s->resource_data; struct socket_data *data = s->resource_data;
unsigned long size = end - start + 1; unsigned long size;
int ret = 0; int ret = 0;
#if defined(CONFIG_X86) #if defined(CONFIG_X86)
...@@ -814,6 +820,8 @@ static int adjust_io(struct pcmcia_socket *s, unsigned int action, unsigned long ...@@ -814,6 +820,8 @@ static int adjust_io(struct pcmcia_socket *s, unsigned int action, unsigned long
start = 0x100; start = 0x100;
#endif #endif
size = end - start + 1;
if (end < start) if (end < start)
return -EINVAL; return -EINVAL;
......
...@@ -105,6 +105,10 @@ struct serial_cfg_mem { ...@@ -105,6 +105,10 @@ struct serial_cfg_mem {
* manfid 0x0160, 0x0104 * manfid 0x0160, 0x0104
* This card appears to have a 14.7456MHz clock. * This card appears to have a 14.7456MHz clock.
*/ */
/* Generic Modem: MD55x (GPRS/EDGE) have
* Elan VPU16551 UART with 14.7456MHz oscillator
* manfid 0x015D, 0x4C45
*/
static void quirk_setup_brainboxes_0104(struct pcmcia_device *link, struct uart_port *port) static void quirk_setup_brainboxes_0104(struct pcmcia_device *link, struct uart_port *port)
{ {
port->uartclk = 14745600; port->uartclk = 14745600;
...@@ -195,6 +199,11 @@ static const struct serial_quirk quirks[] = { ...@@ -195,6 +199,11 @@ static const struct serial_quirk quirks[] = {
.prodid = 0x0104, .prodid = 0x0104,
.multi = -1, .multi = -1,
.setup = quirk_setup_brainboxes_0104, .setup = quirk_setup_brainboxes_0104,
}, {
.manfid = 0x015D,
.prodid = 0x4C45,
.multi = -1,
.setup = quirk_setup_brainboxes_0104,
}, { }, {
.manfid = MANFID_IBM, .manfid = MANFID_IBM,
.prodid = ~0, .prodid = ~0,
......
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