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.
This commit is contained in:
Linus Torvalds 2010-03-18 11:04:59 -07:00
commit 1097d7cef6
8 changed files with 86 additions and 42 deletions

View File

@ -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.map_size = 0x1000;
sockets[i].socket.irq_mask = 0; sockets[i].socket.irq_mask = 0;
sockets[i].socket.pci_irq = dev->irq; sockets[i].socket.pci_irq = dev->irq;
sockets[i].socket.cb_dev = dev;
sockets[i].socket.owner = THIS_MODULE; sockets[i].socket.owner = THIS_MODULE;
sockets[i].number = i; sockets[i].number = i;

View File

@ -95,6 +95,7 @@
#define I365_CSC_DETECT 0x08 #define I365_CSC_DETECT 0x08
#define I365_CSC_ANY 0x0F #define I365_CSC_ANY 0x0F
#define I365_CSC_GPI 0x10 #define I365_CSC_GPI 0x10
#define I365_CSC_IRQ_MASK 0xF0
/* Flags for I365_ADDRWIN */ /* Flags for I365_ADDRWIN */
#define I365_ENA_IO(map) (0x40 << (map)) #define I365_ENA_IO(map) (0x40 << (map))

View File

@ -256,6 +256,7 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
{ {
struct pcmcia_socket *s; struct pcmcia_socket *s;
config_t *c; config_t *c;
int ret;
s = p_dev->socket; s = p_dev->socket;
@ -264,13 +265,13 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
if (!(s->state & SOCKET_PRESENT)) { if (!(s->state & SOCKET_PRESENT)) {
dev_dbg(&s->dev, "No card present\n"); dev_dbg(&s->dev, "No card present\n");
mutex_unlock(&s->ops_mutex); ret = -ENODEV;
return -ENODEV; goto unlock;
} }
if (!(c->state & CONFIG_LOCKED)) { if (!(c->state & CONFIG_LOCKED)) {
dev_dbg(&s->dev, "Configuration isnt't locked\n"); dev_dbg(&s->dev, "Configuration isnt't locked\n");
mutex_unlock(&s->ops_mutex); ret = -EACCES;
return -EACCES; goto unlock;
} }
if (mod->Attributes & CONF_IRQ_CHANGE_VALID) { 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) { if (mod->Attributes & CONF_VCC_CHANGE_VALID) {
dev_dbg(&s->dev, "changing Vcc is not allowed at this time\n"); 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 */ /* 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)) { (mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
if (mod->Vpp1 != mod->Vpp2) { if (mod->Vpp1 != mod->Vpp2) {
dev_dbg(&s->dev, "Vpp1 and Vpp2 must be the same\n"); dev_dbg(&s->dev, "Vpp1 and Vpp2 must be the same\n");
mutex_unlock(&s->ops_mutex); ret = -EINVAL;
return -EINVAL; goto unlock;
} }
s->socket.Vpp = mod->Vpp1; s->socket.Vpp = mod->Vpp1;
if (s->ops->set_socket(s, &s->socket)) { if (s->ops->set_socket(s, &s->socket)) {
mutex_unlock(&s->ops_mutex);
dev_printk(KERN_WARNING, &s->dev, dev_printk(KERN_WARNING, &s->dev,
"Unable to set VPP\n"); "Unable to set VPP\n");
return -EIO; ret = -EIO;
goto unlock;
} }
} else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) || } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) ||
(mod->Attributes & CONF_VPP2_CHANGE_VALID)) { (mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
dev_dbg(&s->dev, "changing Vcc is not allowed at this time\n"); dev_dbg(&s->dev, "changing Vcc is not allowed at this time\n");
mutex_unlock(&s->ops_mutex); ret = -EINVAL;
return -EINVAL; goto unlock;
} }
if (mod->Attributes & CONF_IO_CHANGE_WIDTH) { 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); s->ops->set_io_map(s, &io_on);
} }
} }
ret = 0;
unlock:
mutex_unlock(&s->ops_mutex); mutex_unlock(&s->ops_mutex);
return 0; return ret;
} /* modify_configuration */ } /* modify_configuration */
EXPORT_SYMBOL(pcmcia_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 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 (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 */
irq = s->irq.AssignedIRQ; irq = s->irq.AssignedIRQ;

View File

@ -671,6 +671,7 @@ static int __devinit pd6729_pci_probe(struct pci_dev *dev,
socket[i].socket.map_size = 0x1000; socket[i].socket.map_size = 0x1000;
socket[i].socket.irq_mask = mask; socket[i].socket.irq_mask = mask;
socket[i].socket.pci_irq = dev->irq; socket[i].socket.pci_irq = dev->irq;
socket[i].socket.cb_dev = dev;
socket[i].socket.owner = THIS_MODULE; socket[i].socket.owner = THIS_MODULE;
socket[i].number = i; socket[i].number = i;

View File

@ -296,7 +296,7 @@ static int ti_init(struct yenta_socket *socket)
u8 new, reg = exca_readb(socket, I365_INTCTL); u8 new, reg = exca_readb(socket, I365_INTCTL);
new = reg & ~I365_INTR_ENA; new = reg & ~I365_INTR_ENA;
if (socket->cb_irq) if (socket->dev->irq)
new |= I365_INTR_ENA; new |= I365_INTR_ENA;
if (new != reg) if (new != reg)
exca_writeb(socket, I365_INTCTL, new); exca_writeb(socket, I365_INTCTL, new);
@ -316,14 +316,47 @@ static int ti_override(struct yenta_socket *socket)
return 0; 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) static int ti113x_override(struct yenta_socket *socket)
{ {
u8 cardctl; u8 cardctl;
cardctl = config_readb(socket, TI113X_CARD_CONTROL); cardctl = config_readb(socket, TI113X_CARD_CONTROL);
cardctl &= ~(TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_IREQ | TI113X_CCR_PCI_CSC); 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; 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); config_writeb(socket, TI113X_CARD_CONTROL, cardctl);
return ti_override(socket); return ti_override(socket);

View File

@ -105,6 +105,7 @@ typedef struct vrc4171_socket {
char name[24]; char name[24];
int csc_irq; int csc_irq;
int io_irq; int io_irq;
spinlock_t lock;
} vrc4171_socket_t; } vrc4171_socket_t;
static vrc4171_socket_t vrc4171_sockets[CARD_MAX_SLOTS]; 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; slot = sock->sock;
socket = &vrc4171_sockets[slot]; socket = &vrc4171_sockets[slot];
spin_lock_irq(&sock->lock); spin_lock_irq(&socket->lock);
voltage = set_Vcc_value(state->Vcc); voltage = set_Vcc_value(state->Vcc);
exca_write_byte(slot, CARD_VOLTAGE_SELECT, voltage); 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; cscint |= I365_CSC_DETECT;
exca_write_byte(slot, I365_CSCINT, cscint); exca_write_byte(slot, I365_CSCINT, cscint);
spin_unlock_irq(&sock->lock); spin_unlock_irq(&socket->lock);
return 0; return 0;
} }

View File

@ -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' " MODULE_PARM_DESC(o2_speedup, "Use prefetch/burst for O2-bridges: 'on', 'off' "
"or 'default' (uses recommended behaviour for the detected bridge)"); "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) #define debug(x, s, args...) dev_dbg(&s->dev->dev, x, ##args)
/* Don't ask.. */ /* Don't ask.. */
@ -54,6 +66,8 @@ MODULE_PARM_DESC(o2_speedup, "Use prefetch/burst for O2-bridges: 'on', 'off' "
*/ */
#ifdef CONFIG_YENTA_TI #ifdef CONFIG_YENTA_TI
static int yenta_probe_cb_irq(struct yenta_socket *socket); 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 #endif
@ -329,8 +343,8 @@ static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
/* ISA interrupt control? */ /* ISA interrupt control? */
intr = exca_readb(socket, I365_INTCTL); intr = exca_readb(socket, I365_INTCTL);
intr = (intr & ~0xf); intr = (intr & ~0xf);
if (!socket->cb_irq) { if (!socket->dev->irq) {
intr |= state->io_irq; intr |= socket->cb_irq ? socket->cb_irq : state->io_irq;
bridge |= CB_BRIDGE_INTR; bridge |= CB_BRIDGE_INTR;
} }
exca_writeb(socket, I365_INTCTL, 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 = exca_readb(socket, I365_INTCTL) & (I365_RING_ENA | I365_INTR_ENA);
reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET; reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET;
reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0; 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; reg |= state->io_irq;
bridge |= CB_BRIDGE_INTR; 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); exca_writeb(socket, I365_POWER, reg);
/* CSC interrupt: no ISA irq for CSC */ /* 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->flags & SS_IOCARD) {
if (state->csc_mask & SS_STSCHG) if (state->csc_mask & SS_STSCHG)
reg |= I365_CSC_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) static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mask)
{ {
int i; int i;
unsigned long val; unsigned long val;
u32 mask; u32 mask;
u8 reg;
/* /*
* Probe for usable interrupts using the force * 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_EVENT, -1);
cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK); cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK);
reg = exca_readb(socket, I365_CSCINT);
exca_writeb(socket, I365_CSCINT, 0); exca_writeb(socket, I365_CSCINT, 0);
val = probe_irq_on() & isa_irq_mask; val = probe_irq_on() & isa_irq_mask;
for (i = 1; i < 16; i++) { 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_EVENT, -1);
} }
cb_writel(socket, CB_SOCKET_MASK, 0); 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; 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 */ /* probes the PCI interrupt, use only on override functions */
static int yenta_probe_cb_irq(struct yenta_socket *socket) static int yenta_probe_cb_irq(struct yenta_socket *socket)
{ {
u8 reg;
if (!socket->cb_irq) if (!socket->cb_irq)
return -1; return -1;
@ -979,7 +988,8 @@ static int yenta_probe_cb_irq(struct yenta_socket *socket)
} }
/* generate interrupt, wait */ /* 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_EVENT, -1);
cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK); cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK);
cb_writel(socket, CB_SOCKET_FORCE, CB_FCARDSTS); cb_writel(socket, CB_SOCKET_FORCE, CB_FCARDSTS);
@ -988,7 +998,7 @@ static int yenta_probe_cb_irq(struct yenta_socket *socket)
/* disable interrupts */ /* disable interrupts */
cb_writel(socket, CB_SOCKET_MASK, 0); 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); cb_writel(socket, CB_SOCKET_EVENT, -1);
exca_readb(socket, I365_CSC); exca_readb(socket, I365_CSC);

View File

@ -1717,6 +1717,7 @@ static int nsp_cs_config(struct pcmcia_device *link)
cfg_mem->data = data; cfg_mem->data = data;
ret = pcmcia_loop_config(link, nsp_cs_config_check, cfg_mem); ret = pcmcia_loop_config(link, nsp_cs_config_check, cfg_mem);
if (ret)
goto cs_failed; goto cs_failed;
if (link->conf.Attributes & CONF_ENABLE_IRQ) { if (link->conf.Attributes & CONF_ENABLE_IRQ) {