diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-18 11:04:59 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-18 11:04:59 -0700 |
commit | 1097d7cef683c30f9768007daae2e961a0686a10 (patch) | |
tree | 1dc8f3fc26c6c4b9f5366e94cf4c20490f7f3203 /drivers | |
parent | 57b552ba0b2faf7cce66d476ef8ce7f6210c62fd (diff) | |
parent | 4e06e240dcbb803433ee31bfe89a3e785a77cd3b (diff) |
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: resource, fix lock imbalance
pcmcia: add important if statement
pcmcia: re-route Cardbus IRQ to ISA on ti1130 bridges if necessary
pcmcia: allow for cb_irq to differ from pci_dev's irq in yenta_socket
pcmcia: honor saved flags in yenta_socket's I365_CSCINT register
pcmcia: revert "irq probe can be done without risking an IRQ storm"
pcmcia: pd6729, i82092: use parent (PCI) resources
pcmcia/vrc4171: use local spinlock for device local lock.
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/pcmcia/i82092.c | 1 | ||||
-rw-r--r-- | drivers/pcmcia/i82365.h | 1 | ||||
-rw-r--r-- | drivers/pcmcia/pcmcia_resource.c | 36 | ||||
-rw-r--r-- | drivers/pcmcia/pd6729.c | 1 | ||||
-rw-r--r-- | drivers/pcmcia/ti113x.h | 37 | ||||
-rw-r--r-- | drivers/pcmcia/vrc4171_card.c | 5 | ||||
-rw-r--r-- | drivers/pcmcia/yenta_socket.c | 46 | ||||
-rw-r--r-- | drivers/scsi/pcmcia/nsp_cs.c | 1 |
8 files changed, 86 insertions, 42 deletions
diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c index a04f21c8170..f5da6265331 100644 --- a/drivers/pcmcia/i82092.c +++ b/drivers/pcmcia/i82092.c @@ -133,6 +133,7 @@ static int __devinit i82092aa_pci_probe(struct pci_dev *dev, const struct pci_de sockets[i].socket.map_size = 0x1000; sockets[i].socket.irq_mask = 0; sockets[i].socket.pci_irq = dev->irq; + sockets[i].socket.cb_dev = dev; sockets[i].socket.owner = THIS_MODULE; sockets[i].number = i; diff --git a/drivers/pcmcia/i82365.h b/drivers/pcmcia/i82365.h index 849ef1b5d68..3f84d7a2dc8 100644 --- a/drivers/pcmcia/i82365.h +++ b/drivers/pcmcia/i82365.h @@ -95,6 +95,7 @@ #define I365_CSC_DETECT 0x08 #define I365_CSC_ANY 0x0F #define I365_CSC_GPI 0x10 +#define I365_CSC_IRQ_MASK 0xF0 /* Flags for I365_ADDRWIN */ #define I365_ENA_IO(map) (0x40 << (map)) diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index b2df04199a2..c4612c52e4c 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -256,6 +256,7 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, { struct pcmcia_socket *s; config_t *c; + int ret; s = p_dev->socket; @@ -264,13 +265,13 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, if (!(s->state & SOCKET_PRESENT)) { dev_dbg(&s->dev, "No card present\n"); - mutex_unlock(&s->ops_mutex); - return -ENODEV; + ret = -ENODEV; + goto unlock; } if (!(c->state & CONFIG_LOCKED)) { dev_dbg(&s->dev, "Configuration isnt't locked\n"); - mutex_unlock(&s->ops_mutex); - return -EACCES; + ret = -EACCES; + goto unlock; } if (mod->Attributes & CONF_IRQ_CHANGE_VALID) { @@ -286,7 +287,8 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, if (mod->Attributes & CONF_VCC_CHANGE_VALID) { dev_dbg(&s->dev, "changing Vcc is not allowed at this time\n"); - return -EINVAL; + ret = -EINVAL; + goto unlock; } /* We only allow changing Vpp1 and Vpp2 to the same value */ @@ -294,21 +296,21 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { if (mod->Vpp1 != mod->Vpp2) { dev_dbg(&s->dev, "Vpp1 and Vpp2 must be the same\n"); - mutex_unlock(&s->ops_mutex); - return -EINVAL; + ret = -EINVAL; + goto unlock; } s->socket.Vpp = mod->Vpp1; if (s->ops->set_socket(s, &s->socket)) { - mutex_unlock(&s->ops_mutex); dev_printk(KERN_WARNING, &s->dev, "Unable to set VPP\n"); - return -EIO; + ret = -EIO; + goto unlock; } } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) || (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { dev_dbg(&s->dev, "changing Vcc is not allowed at this time\n"); - mutex_unlock(&s->ops_mutex); - return -EINVAL; + ret = -EINVAL; + goto unlock; } if (mod->Attributes & CONF_IO_CHANGE_WIDTH) { @@ -332,9 +334,11 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, s->ops->set_io_map(s, &io_on); } } + ret = 0; +unlock: mutex_unlock(&s->ops_mutex); - return 0; + return ret; } /* modify_configuration */ EXPORT_SYMBOL(pcmcia_modify_configuration); @@ -752,14 +756,6 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) #ifdef CONFIG_PCMCIA_PROBE -#ifdef IRQ_NOAUTOEN - /* if the underlying IRQ infrastructure allows for it, only allocate - * the IRQ, but do not enable it - */ - if (!(req->Handler)) - type |= IRQ_NOAUTOEN; -#endif /* IRQ_NOAUTOEN */ - if (s->irq.AssignedIRQ != 0) { /* If the interrupt is already assigned, it must be the same */ irq = s->irq.AssignedIRQ; diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c index 7c204910a77..7ba57a565cd 100644 --- a/drivers/pcmcia/pd6729.c +++ b/drivers/pcmcia/pd6729.c @@ -671,6 +671,7 @@ static int __devinit pd6729_pci_probe(struct pci_dev *dev, socket[i].socket.map_size = 0x1000; socket[i].socket.irq_mask = mask; socket[i].socket.pci_irq = dev->irq; + socket[i].socket.cb_dev = dev; socket[i].socket.owner = THIS_MODULE; socket[i].number = i; diff --git a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h index aaa70227bfb..9ffa97d0b16 100644 --- a/drivers/pcmcia/ti113x.h +++ b/drivers/pcmcia/ti113x.h @@ -296,7 +296,7 @@ static int ti_init(struct yenta_socket *socket) u8 new, reg = exca_readb(socket, I365_INTCTL); new = reg & ~I365_INTR_ENA; - if (socket->cb_irq) + if (socket->dev->irq) new |= I365_INTR_ENA; if (new != reg) exca_writeb(socket, I365_INTCTL, new); @@ -316,14 +316,47 @@ static int ti_override(struct yenta_socket *socket) return 0; } +static void ti113x_use_isa_irq(struct yenta_socket *socket) +{ + int isa_irq = -1; + u8 intctl; + u32 isa_irq_mask = 0; + + if (!isa_probe) + return; + + /* get a free isa int */ + isa_irq_mask = yenta_probe_irq(socket, isa_interrupts); + if (!isa_irq_mask) + return; /* no useable isa irq found */ + + /* choose highest available */ + for (; isa_irq_mask; isa_irq++) + isa_irq_mask >>= 1; + socket->cb_irq = isa_irq; + + exca_writeb(socket, I365_CSCINT, (isa_irq << 4)); + + intctl = exca_readb(socket, I365_INTCTL); + intctl &= ~(I365_INTR_ENA | I365_IRQ_MASK); /* CSC Enable */ + exca_writeb(socket, I365_INTCTL, intctl); + + dev_info(&socket->dev->dev, + "Yenta TI113x: using isa irq %d for CardBus\n", isa_irq); +} + + static int ti113x_override(struct yenta_socket *socket) { u8 cardctl; cardctl = config_readb(socket, TI113X_CARD_CONTROL); cardctl &= ~(TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_IREQ | TI113X_CCR_PCI_CSC); - if (socket->cb_irq) + if (socket->dev->irq) cardctl |= TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_CSC | TI113X_CCR_PCI_IREQ; + else + ti113x_use_isa_irq(socket); + config_writeb(socket, TI113X_CARD_CONTROL, cardctl); return ti_override(socket); diff --git a/drivers/pcmcia/vrc4171_card.c b/drivers/pcmcia/vrc4171_card.c index c9fcbdc164e..aaccdb9f4ba 100644 --- a/drivers/pcmcia/vrc4171_card.c +++ b/drivers/pcmcia/vrc4171_card.c @@ -105,6 +105,7 @@ typedef struct vrc4171_socket { char name[24]; int csc_irq; int io_irq; + spinlock_t lock; } vrc4171_socket_t; static vrc4171_socket_t vrc4171_sockets[CARD_MAX_SLOTS]; @@ -327,7 +328,7 @@ static int pccard_set_socket(struct pcmcia_socket *sock, socket_state_t *state) slot = sock->sock; socket = &vrc4171_sockets[slot]; - spin_lock_irq(&sock->lock); + spin_lock_irq(&socket->lock); voltage = set_Vcc_value(state->Vcc); exca_write_byte(slot, CARD_VOLTAGE_SELECT, voltage); @@ -370,7 +371,7 @@ static int pccard_set_socket(struct pcmcia_socket *sock, socket_state_t *state) cscint |= I365_CSC_DETECT; exca_write_byte(slot, I365_CSCINT, cscint); - spin_unlock_irq(&sock->lock); + spin_unlock_irq(&socket->lock); return 0; } diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index 967c766f53b..418988ab6ed 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c @@ -42,6 +42,18 @@ module_param_string(o2_speedup, o2_speedup, sizeof(o2_speedup), 0444); MODULE_PARM_DESC(o2_speedup, "Use prefetch/burst for O2-bridges: 'on', 'off' " "or 'default' (uses recommended behaviour for the detected bridge)"); +/* + * Only probe "regular" interrupts, don't + * touch dangerous spots like the mouse irq, + * because there are mice that apparently + * get really confused if they get fondled + * too intimately. + * + * Default to 11, 10, 9, 7, 6, 5, 4, 3. + */ +static u32 isa_interrupts = 0x0ef8; + + #define debug(x, s, args...) dev_dbg(&s->dev->dev, x, ##args) /* Don't ask.. */ @@ -54,6 +66,8 @@ MODULE_PARM_DESC(o2_speedup, "Use prefetch/burst for O2-bridges: 'on', 'off' " */ #ifdef CONFIG_YENTA_TI static int yenta_probe_cb_irq(struct yenta_socket *socket); +static unsigned int yenta_probe_irq(struct yenta_socket *socket, + u32 isa_irq_mask); #endif @@ -329,8 +343,8 @@ static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state) /* ISA interrupt control? */ intr = exca_readb(socket, I365_INTCTL); intr = (intr & ~0xf); - if (!socket->cb_irq) { - intr |= state->io_irq; + if (!socket->dev->irq) { + intr |= socket->cb_irq ? socket->cb_irq : state->io_irq; bridge |= CB_BRIDGE_INTR; } exca_writeb(socket, I365_INTCTL, intr); @@ -340,7 +354,7 @@ static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state) reg = exca_readb(socket, I365_INTCTL) & (I365_RING_ENA | I365_INTR_ENA); reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET; reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0; - if (state->io_irq != socket->cb_irq) { + if (state->io_irq != socket->dev->irq) { reg |= state->io_irq; bridge |= CB_BRIDGE_INTR; } @@ -356,7 +370,9 @@ static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state) exca_writeb(socket, I365_POWER, reg); /* CSC interrupt: no ISA irq for CSC */ - reg = I365_CSC_DETECT; + reg = exca_readb(socket, I365_CSCINT); + reg &= I365_CSC_IRQ_MASK; + reg |= I365_CSC_DETECT; if (state->flags & SS_IOCARD) { if (state->csc_mask & SS_STSCHG) reg |= I365_CSC_STSCHG; @@ -896,22 +912,12 @@ static struct cardbus_type cardbus_type[] = { }; -/* - * Only probe "regular" interrupts, don't - * touch dangerous spots like the mouse irq, - * because there are mice that apparently - * get really confused if they get fondled - * too intimately. - * - * Default to 11, 10, 9, 7, 6, 5, 4, 3. - */ -static u32 isa_interrupts = 0x0ef8; - static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mask) { int i; unsigned long val; u32 mask; + u8 reg; /* * Probe for usable interrupts using the force @@ -919,6 +925,7 @@ static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mas */ cb_writel(socket, CB_SOCKET_EVENT, -1); cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK); + reg = exca_readb(socket, I365_CSCINT); exca_writeb(socket, I365_CSCINT, 0); val = probe_irq_on() & isa_irq_mask; for (i = 1; i < 16; i++) { @@ -930,7 +937,7 @@ static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mas cb_writel(socket, CB_SOCKET_EVENT, -1); } cb_writel(socket, CB_SOCKET_MASK, 0); - exca_writeb(socket, I365_CSCINT, 0); + exca_writeb(socket, I365_CSCINT, reg); mask = probe_irq_mask(val) & 0xffff; @@ -967,6 +974,8 @@ static irqreturn_t yenta_probe_handler(int irq, void *dev_id) /* probes the PCI interrupt, use only on override functions */ static int yenta_probe_cb_irq(struct yenta_socket *socket) { + u8 reg; + if (!socket->cb_irq) return -1; @@ -979,7 +988,8 @@ static int yenta_probe_cb_irq(struct yenta_socket *socket) } /* generate interrupt, wait */ - exca_writeb(socket, I365_CSCINT, I365_CSC_STSCHG); + reg = exca_readb(socket, I365_CSCINT); + exca_writeb(socket, I365_CSCINT, reg | I365_CSC_STSCHG); cb_writel(socket, CB_SOCKET_EVENT, -1); cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK); cb_writel(socket, CB_SOCKET_FORCE, CB_FCARDSTS); @@ -988,7 +998,7 @@ static int yenta_probe_cb_irq(struct yenta_socket *socket) /* disable interrupts */ cb_writel(socket, CB_SOCKET_MASK, 0); - exca_writeb(socket, I365_CSCINT, 0); + exca_writeb(socket, I365_CSCINT, reg); cb_writel(socket, CB_SOCKET_EVENT, -1); exca_readb(socket, I365_CSC); diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index c2341af587a..02124645487 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -1717,6 +1717,7 @@ static int nsp_cs_config(struct pcmcia_device *link) cfg_mem->data = data; ret = pcmcia_loop_config(link, nsp_cs_config_check, cfg_mem); + if (ret) goto cs_failed; if (link->conf.Attributes & CONF_ENABLE_IRQ) { |