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
This commit is contained in:
commit
27ee896370
@ -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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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,10 +866,8 @@ 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))
|
||||||
|
return 0;
|
||||||
if (!dev->socket->fake_cis)
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (did->match_flags & PCMCIA_DEV_ID_MATCH_ANONYMOUS) {
|
if (did->match_flags & PCMCIA_DEV_ID_MATCH_ANONYMOUS) {
|
||||||
|
@ -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 the interrupt is already assigned, it must be the same */
|
||||||
|
if (s->irq.AssignedIRQ != 0)
|
||||||
if (s->irq.AssignedIRQ != 0) {
|
|
||||||
/* If the interrupt is already assigned, it must be the same */
|
|
||||||
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,
|
|||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
}
|
}
|
||||||
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
|
|||||||
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
|
|||||||
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 {
|
|||||||
* 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[] = {
|
|||||||
.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,
|
||||||
|
Loading…
Reference in New Issue
Block a user