mirror of
https://github.com/torvalds/linux.git
synced 2024-12-03 01:21:28 +00:00
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:
commit
1097d7cef6
@ -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;
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user