Commit 94a819f8 authored by Dominik Brodowski's avatar Dominik Brodowski

pcmcia: assert locking to struct pcmcia_device

Tested-by: default avatarWolfram Sang <w.sang@pengutronix.de>
Signed-off-by: default avatarDominik Brodowski <linux@dominikbrodowski.net>
parent 3d068261
...@@ -90,3 +90,28 @@ or single-use fields not mentioned): ...@@ -90,3 +90,28 @@ or single-use fields not mentioned):
struct list_head devices_list; struct list_head devices_list;
u8 device_count; u8 device_count;
struct pcmcia_state; struct pcmcia_state;
3. Per PCMCIA-device Data:
--------------------------
The "main" struct pcmcia_devie is protected as follows (read-only fields
or single-use fields not mentioned):
- by pcmcia_socket->ops_mutex:
struct list_head socket_device_list;
struct config_t *function_config;
u16 _irq:1;
u16 _io:1;
u16 _win:4;
u16 _locked:1;
u16 allow_func_id_match:1;
u16 suspended:1;
u16 _removed:1;
- by the PCMCIA driver:
io_req_t io;
irq_req_t irq;
config_req_t conf;
window_handle_t win;
...@@ -835,6 +835,8 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev, ...@@ -835,6 +835,8 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev,
} }
if (did->match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID) { if (did->match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID) {
int ret;
if ((!dev->has_func_id) || (dev->func_id != did->func_id)) if ((!dev->has_func_id) || (dev->func_id != did->func_id))
return 0; return 0;
...@@ -849,11 +851,16 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev, ...@@ -849,11 +851,16 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev,
* after it has re-checked that there is no possible module * after it has re-checked that there is no possible module
* with a prod_id/manf_id/card_id match. * with a prod_id/manf_id/card_id match.
*/ */
mutex_lock(&dev->socket->ops_mutex);
ret = dev->allow_func_id_match;
mutex_unlock(&dev->socket->ops_mutex);
if (!ret) {
dev_dbg(&dev->dev, dev_dbg(&dev->dev,
"skipping FUNC_ID match until userspace interaction\n"); "skipping FUNC_ID match until userspace ACK\n");
if (!dev->allow_func_id_match)
return 0; return 0;
} }
}
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");
...@@ -1079,9 +1086,9 @@ static ssize_t pcmcia_store_allow_func_id_match(struct device *dev, ...@@ -1079,9 +1086,9 @@ static ssize_t pcmcia_store_allow_func_id_match(struct device *dev,
if (!count) if (!count)
return -EINVAL; return -EINVAL;
mutex_lock(&p_dev->socket->skt_mutex); mutex_lock(&p_dev->socket->ops_mutex);
p_dev->allow_func_id_match = 1; p_dev->allow_func_id_match = 1;
mutex_unlock(&p_dev->socket->skt_mutex); mutex_unlock(&p_dev->socket->ops_mutex);
ret = bus_rescan_devices(&pcmcia_bus_type); ret = bus_rescan_devices(&pcmcia_bus_type);
if (ret) if (ret)
...@@ -1114,8 +1121,13 @@ static int pcmcia_dev_suspend(struct device *dev, pm_message_t state) ...@@ -1114,8 +1121,13 @@ static int pcmcia_dev_suspend(struct device *dev, pm_message_t state)
struct pcmcia_driver *p_drv = NULL; struct pcmcia_driver *p_drv = NULL;
int ret = 0; int ret = 0;
if (p_dev->suspended) mutex_lock(&p_dev->socket->ops_mutex);
if (p_dev->suspended) {
mutex_unlock(&p_dev->socket->ops_mutex);
return 0; return 0;
}
p_dev->suspended = 1;
mutex_unlock(&p_dev->socket->ops_mutex);
dev_dbg(dev, "suspending\n"); dev_dbg(dev, "suspending\n");
...@@ -1132,6 +1144,9 @@ static int pcmcia_dev_suspend(struct device *dev, pm_message_t state) ...@@ -1132,6 +1144,9 @@ static int pcmcia_dev_suspend(struct device *dev, pm_message_t state)
"pcmcia: device %s (driver %s) did " "pcmcia: device %s (driver %s) did "
"not want to go to sleep (%d)\n", "not want to go to sleep (%d)\n",
p_dev->devname, p_drv->drv.name, ret); p_dev->devname, p_drv->drv.name, ret);
mutex_lock(&p_dev->socket->ops_mutex);
p_dev->suspended = 0;
mutex_unlock(&p_dev->socket->ops_mutex);
goto out; goto out;
} }
} }
...@@ -1142,8 +1157,6 @@ static int pcmcia_dev_suspend(struct device *dev, pm_message_t state) ...@@ -1142,8 +1157,6 @@ static int pcmcia_dev_suspend(struct device *dev, pm_message_t state)
} }
out: out:
if (!ret)
p_dev->suspended = 1;
return ret; return ret;
} }
...@@ -1154,8 +1167,13 @@ static int pcmcia_dev_resume(struct device *dev) ...@@ -1154,8 +1167,13 @@ static int pcmcia_dev_resume(struct device *dev)
struct pcmcia_driver *p_drv = NULL; struct pcmcia_driver *p_drv = NULL;
int ret = 0; int ret = 0;
if (!p_dev->suspended) mutex_lock(&p_dev->socket->ops_mutex);
if (!p_dev->suspended) {
mutex_unlock(&p_dev->socket->ops_mutex);
return 0; return 0;
}
p_dev->suspended = 0;
mutex_unlock(&p_dev->socket->ops_mutex);
dev_dbg(dev, "resuming\n"); dev_dbg(dev, "resuming\n");
...@@ -1176,8 +1194,6 @@ static int pcmcia_dev_resume(struct device *dev) ...@@ -1176,8 +1194,6 @@ static int pcmcia_dev_resume(struct device *dev)
ret = p_drv->resume(p_dev); ret = p_drv->resume(p_dev);
out: out:
if (!ret)
p_dev->suspended = 0;
return ret; return ret;
} }
......
...@@ -191,14 +191,18 @@ int pcmcia_access_configuration_register(struct pcmcia_device *p_dev, ...@@ -191,14 +191,18 @@ int pcmcia_access_configuration_register(struct pcmcia_device *p_dev,
return -EINVAL; return -EINVAL;
s = p_dev->socket; s = p_dev->socket;
mutex_lock(&s->ops_mutex);
c = p_dev->function_config; c = p_dev->function_config;
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);
return -EACCES; return -EACCES;
} }
addr = (c->ConfigBase + reg->Offset) >> 1; addr = (c->ConfigBase + reg->Offset) >> 1;
mutex_unlock(&s->ops_mutex);
switch (reg->Action) { switch (reg->Action) {
case CS_READ: case CS_READ:
...@@ -254,19 +258,22 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, ...@@ -254,19 +258,22 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
config_t *c; config_t *c;
s = p_dev->socket; s = p_dev->socket;
mutex_lock(&s->ops_mutex);
c = p_dev->function_config; c = p_dev->function_config;
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);
return -ENODEV; return -ENODEV;
} }
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);
return -EACCES; return -EACCES;
} }
if (mod->Attributes & CONF_IRQ_CHANGE_VALID) { if (mod->Attributes & CONF_IRQ_CHANGE_VALID) {
mutex_lock(&s->ops_mutex);
if (mod->Attributes & CONF_ENABLE_IRQ) { if (mod->Attributes & CONF_ENABLE_IRQ) {
c->Attributes |= CONF_ENABLE_IRQ; c->Attributes |= CONF_ENABLE_IRQ;
s->socket.io_irq = s->irq.AssignedIRQ; s->socket.io_irq = s->irq.AssignedIRQ;
...@@ -275,7 +282,6 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, ...@@ -275,7 +282,6 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
s->socket.io_irq = 0; s->socket.io_irq = 0;
} }
s->ops->set_socket(s, &s->socket); s->ops->set_socket(s, &s->socket);
mutex_unlock(&s->ops_mutex);
} }
if (mod->Attributes & CONF_VCC_CHANGE_VALID) { if (mod->Attributes & CONF_VCC_CHANGE_VALID) {
...@@ -288,9 +294,9 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, ...@@ -288,9 +294,9 @@ 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);
return -EINVAL; return -EINVAL;
} }
mutex_lock(&s->ops_mutex);
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); mutex_unlock(&s->ops_mutex);
...@@ -298,10 +304,10 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, ...@@ -298,10 +304,10 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
"Unable to set VPP\n"); "Unable to set VPP\n");
return -EIO; return -EIO;
} }
mutex_unlock(&s->ops_mutex);
} 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);
return -EINVAL; return -EINVAL;
} }
...@@ -311,7 +317,6 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, ...@@ -311,7 +317,6 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
int i; int i;
io_on.speed = io_speed; io_on.speed = io_speed;
mutex_lock(&s->ops_mutex);
for (i = 0; i < MAX_IO_WIN; i++) { for (i = 0; i < MAX_IO_WIN; i++) {
if (!s->io[i].res) if (!s->io[i].res)
continue; continue;
...@@ -326,8 +331,8 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, ...@@ -326,8 +331,8 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
mdelay(40); mdelay(40);
s->ops->set_io_map(s, &io_on); s->ops->set_io_map(s, &io_on);
} }
mutex_unlock(&s->ops_mutex);
} }
mutex_unlock(&s->ops_mutex);
return 0; return 0;
} /* modify_configuration */ } /* modify_configuration */
...@@ -338,10 +343,11 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev) ...@@ -338,10 +343,11 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev)
{ {
pccard_io_map io = { 0, 0, 0, 0, 1 }; pccard_io_map io = { 0, 0, 0, 0, 1 };
struct pcmcia_socket *s = p_dev->socket; struct pcmcia_socket *s = p_dev->socket;
config_t *c = p_dev->function_config; config_t *c;
int i; int i;
mutex_lock(&s->ops_mutex); mutex_lock(&s->ops_mutex);
c = p_dev->function_config;
if (p_dev->_locked) { if (p_dev->_locked) {
p_dev->_locked = 0; p_dev->_locked = 0;
if (--(s->lock_count) == 0) { if (--(s->lock_count) == 0) {
...@@ -381,10 +387,14 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev) ...@@ -381,10 +387,14 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev)
static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req) static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req)
{ {
struct pcmcia_socket *s = p_dev->socket; struct pcmcia_socket *s = p_dev->socket;
config_t *c = p_dev->function_config; int ret = -EINVAL;
config_t *c;
mutex_lock(&s->ops_mutex);
c = p_dev->function_config;
if (!p_dev->_io) if (!p_dev->_io)
return -EINVAL; goto out;
p_dev->_io = 0; p_dev->_io = 0;
...@@ -392,7 +402,7 @@ static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req) ...@@ -392,7 +402,7 @@ static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req)
(c->io.NumPorts1 != req->NumPorts1) || (c->io.NumPorts1 != req->NumPorts1) ||
(c->io.BasePort2 != req->BasePort2) || (c->io.BasePort2 != req->BasePort2) ||
(c->io.NumPorts2 != req->NumPorts2)) (c->io.NumPorts2 != req->NumPorts2))
return -EINVAL; goto out;
c->state &= ~CONFIG_IO_REQ; c->state &= ~CONFIG_IO_REQ;
...@@ -400,30 +410,38 @@ static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req) ...@@ -400,30 +410,38 @@ static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req)
if (req->NumPorts2) if (req->NumPorts2)
release_io_space(s, req->BasePort2, req->NumPorts2); release_io_space(s, req->BasePort2, req->NumPorts2);
return 0; out:
mutex_unlock(&s->ops_mutex);
return ret;
} /* pcmcia_release_io */ } /* pcmcia_release_io */
static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req)
{ {
struct pcmcia_socket *s = p_dev->socket; struct pcmcia_socket *s = p_dev->socket;
config_t *c = p_dev->function_config; config_t *c;
int ret = -EINVAL;
mutex_lock(&s->ops_mutex);
c = p_dev->function_config;
if (!p_dev->_irq) if (!p_dev->_irq)
return -EINVAL; goto out;
p_dev->_irq = 0; p_dev->_irq = 0;
if (c->state & CONFIG_LOCKED) if (c->state & CONFIG_LOCKED)
return -EACCES; goto out;
if (c->irq.Attributes != req->Attributes) { if (c->irq.Attributes != req->Attributes) {
dev_dbg(&s->dev, "IRQ attributes must match assigned ones\n"); dev_dbg(&s->dev, "IRQ attributes must match assigned ones\n");
return -EINVAL; goto out;
} }
mutex_lock(&s->ops_mutex);
if (s->irq.AssignedIRQ != req->AssignedIRQ) { if (s->irq.AssignedIRQ != req->AssignedIRQ) {
mutex_unlock(&s->ops_mutex);
dev_dbg(&s->dev, "IRQ must match assigned one\n"); dev_dbg(&s->dev, "IRQ must match assigned one\n");
return -EINVAL; goto out;
} }
if (--s->irq.Config == 0) { if (--s->irq.Config == 0) {
c->state &= ~CONFIG_IRQ_REQ; c->state &= ~CONFIG_IRQ_REQ;
...@@ -436,9 +454,12 @@ static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) ...@@ -436,9 +454,12 @@ static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req)
#ifdef CONFIG_PCMCIA_PROBE #ifdef CONFIG_PCMCIA_PROBE
pcmcia_used_irq[req->AssignedIRQ]--; pcmcia_used_irq[req->AssignedIRQ]--;
#endif #endif
ret = 0;
out:
mutex_unlock(&s->ops_mutex); mutex_unlock(&s->ops_mutex);
return 0; return ret;
} /* pcmcia_release_irq */ } /* pcmcia_release_irq */
...@@ -495,13 +516,15 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, ...@@ -495,13 +516,15 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
dev_dbg(&s->dev, "IntType may not be INT_CARDBUS\n"); dev_dbg(&s->dev, "IntType may not be INT_CARDBUS\n");
return -EINVAL; return -EINVAL;
} }
mutex_lock(&s->ops_mutex);
c = p_dev->function_config; c = p_dev->function_config;
if (c->state & CONFIG_LOCKED) { if (c->state & CONFIG_LOCKED) {
mutex_unlock(&s->ops_mutex);
dev_dbg(&s->dev, "Configuration is locked\n"); dev_dbg(&s->dev, "Configuration is locked\n");
return -EACCES; return -EACCES;
} }
mutex_lock(&s->ops_mutex);
/* Do power control. We don't allow changes in Vcc. */ /* Do power control. We don't allow changes in Vcc. */
s->socket.Vpp = req->Vpp; s->socket.Vpp = req->Vpp;
if (s->ops->set_socket(s, &s->socket)) { if (s->ops->set_socket(s, &s->socket)) {
...@@ -615,58 +638,65 @@ int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req) ...@@ -615,58 +638,65 @@ int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req)
{ {
struct pcmcia_socket *s = p_dev->socket; struct pcmcia_socket *s = p_dev->socket;
config_t *c; config_t *c;
int ret = -EINVAL;
mutex_lock(&s->ops_mutex);
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");
return -ENODEV; goto out;
} }
if (!req) if (!req)
return -EINVAL; goto out;
c = p_dev->function_config; c = p_dev->function_config;
if (c->state & CONFIG_LOCKED) { if (c->state & CONFIG_LOCKED) {
dev_dbg(&s->dev, "Configuration is locked\n"); dev_dbg(&s->dev, "Configuration is locked\n");
return -EACCES; goto out;
} }
if (c->state & CONFIG_IO_REQ) { if (c->state & CONFIG_IO_REQ) {
dev_dbg(&s->dev, "IO already configured\n"); dev_dbg(&s->dev, "IO already configured\n");
return -EBUSY; goto out;
} }
if (req->Attributes1 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS)) { if (req->Attributes1 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS)) {
dev_dbg(&s->dev, "bad attribute setting for IO region 1\n"); dev_dbg(&s->dev, "bad attribute setting for IO region 1\n");
return -EINVAL; goto out;
} }
if ((req->NumPorts2 > 0) && if ((req->NumPorts2 > 0) &&
(req->Attributes2 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS))) { (req->Attributes2 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS))) {
dev_dbg(&s->dev, "bad attribute setting for IO region 2\n"); dev_dbg(&s->dev, "bad attribute setting for IO region 2\n");
return -EINVAL; goto out;
} }
mutex_lock(&s->ops_mutex);
dev_dbg(&s->dev, "trying to allocate resource 1\n"); dev_dbg(&s->dev, "trying to allocate resource 1\n");
if (alloc_io_space(s, req->Attributes1, &req->BasePort1, ret = alloc_io_space(s, req->Attributes1, &req->BasePort1,
req->NumPorts1, req->IOAddrLines)) { req->NumPorts1, req->IOAddrLines);
if (ret) {
dev_dbg(&s->dev, "allocation of resource 1 failed\n"); dev_dbg(&s->dev, "allocation of resource 1 failed\n");
mutex_unlock(&s->ops_mutex); goto out;
return -EBUSY;
} }
if (req->NumPorts2) { if (req->NumPorts2) {
dev_dbg(&s->dev, "trying to allocate resource 2\n"); dev_dbg(&s->dev, "trying to allocate resource 2\n");
if (alloc_io_space(s, req->Attributes2, &req->BasePort2, ret = alloc_io_space(s, req->Attributes2, &req->BasePort2,
req->NumPorts2, req->IOAddrLines)) { req->NumPorts2, req->IOAddrLines);
if (ret) {
dev_dbg(&s->dev, "allocation of resource 2 failed\n"); dev_dbg(&s->dev, "allocation of resource 2 failed\n");
release_io_space(s, req->BasePort1, req->NumPorts1); release_io_space(s, req->BasePort1, req->NumPorts1);
mutex_unlock(&s->ops_mutex); goto out;
return -EBUSY;
} }
} }
mutex_unlock(&s->ops_mutex);
c->io = *req; c->io = *req;
c->state |= CONFIG_IO_REQ; c->state |= CONFIG_IO_REQ;
p_dev->_io = 1; p_dev->_io = 1;
return 0; dev_dbg(&s->dev, "allocating resources succeeded: %d\n", ret);
out:
mutex_unlock(&s->ops_mutex);
return ret;
} /* pcmcia_request_io */ } /* pcmcia_request_io */
EXPORT_SYMBOL(pcmcia_request_io); EXPORT_SYMBOL(pcmcia_request_io);
...@@ -695,21 +725,22 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) ...@@ -695,21 +725,22 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
int ret = -EINVAL, irq = 0; int ret = -EINVAL, irq = 0;
int type; int type;
mutex_lock(&s->ops_mutex);
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");
return -ENODEV; goto out;
} }
c = p_dev->function_config; c = p_dev->function_config;
if (c->state & CONFIG_LOCKED) { if (c->state & CONFIG_LOCKED) {
dev_dbg(&s->dev, "Configuration is locked\n"); dev_dbg(&s->dev, "Configuration is locked\n");
return -EACCES; goto out;
} }
if (c->state & CONFIG_IRQ_REQ) { if (c->state & CONFIG_IRQ_REQ) {
dev_dbg(&s->dev, "IRQ already configured\n"); dev_dbg(&s->dev, "IRQ already configured\n");
return -EBUSY; goto out;
} }
mutex_lock(&s->ops_mutex);
/* Decide what type of interrupt we are registering */ /* Decide what type of interrupt we are registering */
type = 0; type = 0;
if (s->functions > 1) /* All of this ought to be handled higher up */ if (s->functions > 1) /* All of this ought to be handled higher up */
...@@ -768,7 +799,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) ...@@ -768,7 +799,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
if (ret && !s->irq.AssignedIRQ) { if (ret && !s->irq.AssignedIRQ) {
if (!s->pci_irq) { if (!s->pci_irq) {
dev_printk(KERN_INFO, &s->dev, "no IRQ found\n"); dev_printk(KERN_INFO, &s->dev, "no IRQ found\n");
return ret; goto out;
} }
type = IRQF_SHARED; type = IRQF_SHARED;
irq = s->pci_irq; irq = s->pci_irq;
...@@ -780,7 +811,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) ...@@ -780,7 +811,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
if (ret) { if (ret) {
dev_printk(KERN_INFO, &s->dev, dev_printk(KERN_INFO, &s->dev,
"request_irq() failed\n"); "request_irq() failed\n");
return ret; goto out;
} }
} }
...@@ -803,9 +834,10 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) ...@@ -803,9 +834,10 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
pcmcia_used_irq[irq]++; pcmcia_used_irq[irq]++;
#endif #endif
ret = 0;
out:
mutex_unlock(&s->ops_mutex); mutex_unlock(&s->ops_mutex);
return ret;
return 0;
} /* pcmcia_request_irq */ } /* pcmcia_request_irq */
EXPORT_SYMBOL(pcmcia_request_irq); EXPORT_SYMBOL(pcmcia_request_irq);
......
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