From f9c316f4a2d32e4d03497ecb24e1d2309361a5b8 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Wed, 6 Jan 2010 11:32:22 +0100 Subject: pcmcia: remove some rsrc_mgr indirections Remove rsrc_mgr indirections only used by pcmcia_resource.c Tested-by: Wolfram Sang Signed-off-by: Dominik Brodowski --- drivers/pcmcia/pcmcia_resource.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'drivers/pcmcia/pcmcia_resource.c') diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index d5db95644b6..880b0b63b6a 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -43,6 +43,23 @@ module_param(io_speed, int, 0444); static u8 pcmcia_used_irq[NR_IRQS]; #endif +static int pcmcia_adjust_io_region(struct resource *res, unsigned long start, + unsigned long end, struct pcmcia_socket *s) +{ + if (s->resource_ops->adjust_io_region) + return s->resource_ops->adjust_io_region(res, start, end, s); + return -ENOMEM; +} + +static struct resource *pcmcia_find_io_region(unsigned long base, int num, + unsigned long align, + struct pcmcia_socket *s) +{ + if (s->resource_ops->find_io) + return s->resource_ops->find_io(base, num, align, s); + return NULL; +} + /** alloc_io_space * -- cgit v1.2.3 From a3ac9af56c14c366a76fb4916995e57392c7b7d5 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Wed, 6 Jan 2010 14:03:03 +0100 Subject: pcmcia: remove remaining rsrc_mgr indirections Move rsrc_mgr indirections only used by the pcmcia module to the pcmcia module. Tested-by: Wolfram Sang Signed-off-by: Dominik Brodowski --- drivers/pcmcia/pcmcia_resource.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers/pcmcia/pcmcia_resource.c') diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 880b0b63b6a..8ceb7abc580 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -60,6 +60,22 @@ static struct resource *pcmcia_find_io_region(unsigned long base, int num, return NULL; } +int pcmcia_validate_mem(struct pcmcia_socket *s) +{ + if (s->resource_ops->validate_mem) + return s->resource_ops->validate_mem(s); + /* if there is no callback, we can assume that everything is OK */ + return 0; +} + +struct resource *pcmcia_find_mem_region(u_long base, u_long num, u_long align, + int low, struct pcmcia_socket *s) +{ + if (s->resource_ops->find_mem) + return s->resource_ops->find_mem(base, num, align, low, s); + return NULL; +} + /** alloc_io_space * -- cgit v1.2.3 From 6b8e087b86c59c3941e125738d30cf38014089e0 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 12 Jan 2010 21:42:51 +0100 Subject: pcmcia: add locking to set_mem_map() Protect the pccard_operations callback "set_mem_map" by a new mutex ops_mutex. This mutex also protects the following values in struct pcmcia_socket: pccard_mem_map win[] pccard_mem_map cis_mem void __iomem *cis_virt Tested-by: Wolfram Sang Signed-off-by: Dominik Brodowski --- drivers/pcmcia/pcmcia_resource.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'drivers/pcmcia/pcmcia_resource.c') diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 8ceb7abc580..f31ba89e40d 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -223,6 +223,7 @@ int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t wh, memreq_t *req) { struct pcmcia_socket *s = p_dev->socket; + int ret; wh--; if (wh >= MAX_WIN) @@ -231,12 +232,13 @@ int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t wh, dev_dbg(&s->dev, "failure: requested page is zero\n"); return -EINVAL; } + mutex_lock(&s->ops_mutex); s->win[wh].card_start = req->CardOffset; - if (s->ops->set_mem_map(s, &s->win[wh]) != 0) { - dev_dbg(&s->dev, "failed to set_mem_map\n"); - return -EIO; - } - return 0; + ret = s->ops->set_mem_map(s, &s->win[wh]); + if (ret) + dev_warn(&s->dev, "failed to set_mem_map\n"); + mutex_unlock(&s->ops_mutex); + return ret; } /* pcmcia_map_mem_page */ EXPORT_SYMBOL(pcmcia_map_mem_page); @@ -437,10 +439,12 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, window_handle_t wh) if (wh >= MAX_WIN) return -EINVAL; + mutex_lock(&s->ops_mutex); win = &s->win[wh]; if (!(p_dev->_win & CLIENT_WIN_REQ(wh))) { dev_dbg(&s->dev, "not releasing unknown window\n"); + mutex_unlock(&s->ops_mutex); return -EINVAL; } @@ -456,6 +460,7 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, window_handle_t wh) win->res = NULL; } p_dev->_win &= ~CLIENT_WIN_REQ(wh); + mutex_unlock(&s->ops_mutex); return 0; } /* pcmcia_release_window */ @@ -829,6 +834,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha return -EINVAL; } + mutex_lock(&s->ops_mutex); win = &s->win[w]; if (!(s->features & SS_CAP_STATIC_MAP)) { @@ -836,6 +842,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha (req->Attributes & WIN_MAP_BELOW_1MB), s); if (!win->res) { dev_dbg(&s->dev, "allocating mem region failed\n"); + mutex_unlock(&s->ops_mutex); return -EINVAL; } } @@ -854,8 +861,10 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha if (req->Attributes & WIN_USE_WAIT) win->flags |= MAP_USE_WAIT; win->card_start = 0; + if (s->ops->set_mem_map(s, win) != 0) { dev_dbg(&s->dev, "failed to set memory mapping\n"); + mutex_unlock(&s->ops_mutex); return -EIO; } s->state |= SOCKET_WIN_REQ(w); @@ -866,6 +875,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha else req->Base = win->res->start; + mutex_unlock(&s->ops_mutex); *wh = w + 1; return 0; -- cgit v1.2.3 From 8533ee31cdc08fc1f2533e5f21f8e4abf6a57dfc Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 12 Jan 2010 23:52:19 +0100 Subject: pcmcia: lock ops->set_io_map() As a side effect, io_window_t io[MAX_IO_WIN]; is explicitely protected now. Tested-by: Wolfram Sang Signed-off-by: Dominik Brodowski --- drivers/pcmcia/pcmcia_resource.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/pcmcia/pcmcia_resource.c') diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index f31ba89e40d..4e0aaec5cf9 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -306,6 +306,7 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, int i; io_on.speed = io_speed; + mutex_lock(&s->ops_mutex); for (i = 0; i < MAX_IO_WIN; i++) { if (!s->io[i].res) continue; @@ -320,6 +321,7 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, mdelay(40); s->ops->set_io_map(s, &io_on); } + mutex_unlock(&s->ops_mutex); } return 0; @@ -345,6 +347,7 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev) } if (c->state & CONFIG_LOCKED) { c->state &= ~CONFIG_LOCKED; + mutex_lock(&s->ops_mutex); if (c->state & CONFIG_IO_REQ) for (i = 0; i < MAX_IO_WIN; i++) { if (!s->io[i].res) @@ -355,6 +358,7 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev) io.map = i; s->ops->set_io_map(s, &io); } + mutex_unlock(&s->ops_mutex); } return 0; @@ -562,6 +566,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, /* Configure I/O windows */ if (c->state & CONFIG_IO_REQ) { + mutex_lock(&s->ops_mutex); iomap.speed = io_speed; for (i = 0; i < MAX_IO_WIN; i++) if (s->io[i].res) { @@ -580,6 +585,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, s->ops->set_io_map(s, &iomap); s->io[i].Config++; } + mutex_unlock(&s->ops_mutex); } c->state |= CONFIG_LOCKED; @@ -625,10 +631,12 @@ int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req) return -EINVAL; } + mutex_lock(&s->ops_mutex); dev_dbg(&s->dev, "trying to allocate resource 1\n"); if (alloc_io_space(s, req->Attributes1, &req->BasePort1, req->NumPorts1, req->IOAddrLines)) { dev_dbg(&s->dev, "allocation of resource 1 failed\n"); + mutex_unlock(&s->ops_mutex); return -EBUSY; } @@ -638,9 +646,11 @@ int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req) req->NumPorts2, req->IOAddrLines)) { dev_dbg(&s->dev, "allocation of resource 2 failed\n"); release_io_space(s, req->BasePort1, req->NumPorts1); + mutex_unlock(&s->ops_mutex); return -EBUSY; } } + mutex_unlock(&s->ops_mutex); c->io = *req; c->state |= CONFIG_IO_REQ; -- cgit v1.2.3 From 9e86749cff70fca505c7c1a9dc760d193f27a059 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sat, 16 Jan 2010 00:26:33 +0100 Subject: pcmcia: lock ops->set_socket As a side effect, socket_state_t socket; u_int state; u_int suspended_state; are properly protected now. Tested-by: Wolfram Sang Signed-off-by: Dominik Brodowski --- drivers/pcmcia/pcmcia_resource.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'drivers/pcmcia/pcmcia_resource.c') diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 4e0aaec5cf9..f365ecb9c5c 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -266,6 +266,7 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, } if (mod->Attributes & CONF_IRQ_CHANGE_VALID) { + mutex_lock(&s->ops_mutex); if (mod->Attributes & CONF_ENABLE_IRQ) { c->Attributes |= CONF_ENABLE_IRQ; s->socket.io_irq = s->irq.AssignedIRQ; @@ -274,6 +275,7 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, s->socket.io_irq = 0; } s->ops->set_socket(s, &s->socket); + mutex_unlock(&s->ops_mutex); } if (mod->Attributes & CONF_VCC_CHANGE_VALID) { @@ -288,12 +290,15 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, dev_dbg(&s->dev, "Vpp1 and Vpp2 must be the same\n"); return -EINVAL; } + mutex_lock(&s->ops_mutex); 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; } + mutex_unlock(&s->ops_mutex); } 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"); @@ -336,6 +341,7 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev) config_t *c = p_dev->function_config; int i; + mutex_lock(&s->ops_mutex); if (p_dev->_locked) { p_dev->_locked = 0; if (--(s->lock_count) == 0) { @@ -347,7 +353,6 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev) } if (c->state & CONFIG_LOCKED) { c->state &= ~CONFIG_LOCKED; - mutex_lock(&s->ops_mutex); if (c->state & CONFIG_IO_REQ) for (i = 0; i < MAX_IO_WIN; i++) { if (!s->io[i].res) @@ -358,8 +363,8 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev) io.map = i; s->ops->set_io_map(s, &io); } - mutex_unlock(&s->ops_mutex); } + mutex_unlock(&s->ops_mutex); return 0; } /* pcmcia_release_configuration */ @@ -493,9 +498,11 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, return -EACCES; } + mutex_lock(&s->ops_mutex); /* Do power control. We don't allow changes in Vcc. */ s->socket.Vpp = req->Vpp; if (s->ops->set_socket(s, &s->socket)) { + mutex_unlock(&s->ops_mutex); dev_printk(KERN_WARNING, &s->dev, "Unable to set socket state\n"); return -EINVAL; @@ -518,6 +525,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, s->socket.io_irq = 0; s->ops->set_socket(s, &s->socket); s->lock_count++; + mutex_unlock(&s->ops_mutex); /* Set up CIS configuration registers */ base = c->ConfigBase = req->ConfigBase; @@ -698,6 +706,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) return -EBUSY; } + mutex_lock(&s->ops_mutex); /* Decide what type of interrupt we are registering */ type = 0; if (s->functions > 1) /* All of this ought to be handled higher up */ @@ -791,6 +800,8 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) pcmcia_used_irq[irq]++; #endif + mutex_unlock(&s->ops_mutex); + return 0; } /* pcmcia_request_irq */ EXPORT_SYMBOL(pcmcia_request_irq); -- cgit v1.2.3 From 64d8d46f5f501a19aec4db7ff93faf1b831d05ed Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sat, 16 Jan 2010 01:14:38 +0100 Subject: pcmcia: properly lock skt->irq, skt->irq_mask Tested-by: Wolfram Sang Signed-off-by: Dominik Brodowski --- drivers/pcmcia/pcmcia_resource.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/pcmcia/pcmcia_resource.c') diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index f365ecb9c5c..f0de7b8b123 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -419,7 +419,9 @@ static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) dev_dbg(&s->dev, "IRQ attributes must match assigned ones\n"); return -EINVAL; } + mutex_lock(&s->ops_mutex); if (s->irq.AssignedIRQ != req->AssignedIRQ) { + mutex_unlock(&s->ops_mutex); dev_dbg(&s->dev, "IRQ must match assigned one\n"); return -EINVAL; } @@ -434,6 +436,7 @@ static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) #ifdef CONFIG_PCMCIA_PROBE pcmcia_used_irq[req->AssignedIRQ]--; #endif + mutex_unlock(&s->ops_mutex); return 0; } /* pcmcia_release_irq */ -- cgit v1.2.3 From 94a819f80297e1f635a7cde4ed5317612e512ba7 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sun, 17 Jan 2010 18:31:34 +0100 Subject: pcmcia: assert locking to struct pcmcia_device Tested-by: Wolfram Sang Signed-off-by: Dominik Brodowski --- drivers/pcmcia/pcmcia_resource.c | 122 ++++++++++++++++++++++++--------------- 1 file changed, 77 insertions(+), 45 deletions(-) (limited to 'drivers/pcmcia/pcmcia_resource.c') diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index f0de7b8b123..b2df04199a2 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -191,14 +191,18 @@ int pcmcia_access_configuration_register(struct pcmcia_device *p_dev, return -EINVAL; s = p_dev->socket; + + mutex_lock(&s->ops_mutex); c = p_dev->function_config; if (!(c->state & CONFIG_LOCKED)) { dev_dbg(&s->dev, "Configuration isnt't locked\n"); + mutex_unlock(&s->ops_mutex); return -EACCES; } addr = (c->ConfigBase + reg->Offset) >> 1; + mutex_unlock(&s->ops_mutex); switch (reg->Action) { case CS_READ: @@ -254,19 +258,22 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, config_t *c; s = p_dev->socket; + + mutex_lock(&s->ops_mutex); c = p_dev->function_config; if (!(s->state & SOCKET_PRESENT)) { dev_dbg(&s->dev, "No card present\n"); + mutex_unlock(&s->ops_mutex); return -ENODEV; } if (!(c->state & CONFIG_LOCKED)) { dev_dbg(&s->dev, "Configuration isnt't locked\n"); + mutex_unlock(&s->ops_mutex); return -EACCES; } if (mod->Attributes & CONF_IRQ_CHANGE_VALID) { - mutex_lock(&s->ops_mutex); if (mod->Attributes & CONF_ENABLE_IRQ) { c->Attributes |= CONF_ENABLE_IRQ; s->socket.io_irq = s->irq.AssignedIRQ; @@ -275,7 +282,6 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, s->socket.io_irq = 0; } s->ops->set_socket(s, &s->socket); - mutex_unlock(&s->ops_mutex); } if (mod->Attributes & CONF_VCC_CHANGE_VALID) { @@ -288,9 +294,9 @@ 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; } - mutex_lock(&s->ops_mutex); s->socket.Vpp = mod->Vpp1; if (s->ops->set_socket(s, &s->socket)) { mutex_unlock(&s->ops_mutex); @@ -298,10 +304,10 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, "Unable to set VPP\n"); return -EIO; } - mutex_unlock(&s->ops_mutex); } 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; } @@ -311,7 +317,6 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, int i; io_on.speed = io_speed; - mutex_lock(&s->ops_mutex); for (i = 0; i < MAX_IO_WIN; i++) { if (!s->io[i].res) continue; @@ -326,8 +331,8 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, mdelay(40); s->ops->set_io_map(s, &io_on); } - mutex_unlock(&s->ops_mutex); } + mutex_unlock(&s->ops_mutex); return 0; } /* modify_configuration */ @@ -338,10 +343,11 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev) { pccard_io_map io = { 0, 0, 0, 0, 1 }; struct pcmcia_socket *s = p_dev->socket; - config_t *c = p_dev->function_config; + config_t *c; int i; mutex_lock(&s->ops_mutex); + c = p_dev->function_config; if (p_dev->_locked) { p_dev->_locked = 0; if (--(s->lock_count) == 0) { @@ -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) { 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) - return -EINVAL; + goto out; p_dev->_io = 0; @@ -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.BasePort2 != req->BasePort2) || (c->io.NumPorts2 != req->NumPorts2)) - return -EINVAL; + goto out; c->state &= ~CONFIG_IO_REQ; @@ -400,30 +410,38 @@ static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req) if (req->NumPorts2) release_io_space(s, req->BasePort2, req->NumPorts2); - return 0; +out: + mutex_unlock(&s->ops_mutex); + + return ret; } /* pcmcia_release_io */ static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) { 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) - return -EINVAL; + goto out; + p_dev->_irq = 0; if (c->state & CONFIG_LOCKED) - return -EACCES; + goto out; + if (c->irq.Attributes != req->Attributes) { 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) { - mutex_unlock(&s->ops_mutex); dev_dbg(&s->dev, "IRQ must match assigned one\n"); - return -EINVAL; + goto out; } if (--s->irq.Config == 0) { c->state &= ~CONFIG_IRQ_REQ; @@ -436,9 +454,12 @@ static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) #ifdef CONFIG_PCMCIA_PROBE pcmcia_used_irq[req->AssignedIRQ]--; #endif + ret = 0; + +out: mutex_unlock(&s->ops_mutex); - return 0; + return ret; } /* pcmcia_release_irq */ @@ -495,13 +516,15 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, dev_dbg(&s->dev, "IntType may not be INT_CARDBUS\n"); return -EINVAL; } + + mutex_lock(&s->ops_mutex); c = p_dev->function_config; if (c->state & CONFIG_LOCKED) { + mutex_unlock(&s->ops_mutex); dev_dbg(&s->dev, "Configuration is locked\n"); return -EACCES; } - mutex_lock(&s->ops_mutex); /* Do power control. We don't allow changes in Vcc. */ s->socket.Vpp = req->Vpp; 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) { struct pcmcia_socket *s = p_dev->socket; config_t *c; + int ret = -EINVAL; + + mutex_lock(&s->ops_mutex); if (!(s->state & SOCKET_PRESENT)) { dev_dbg(&s->dev, "No card present\n"); - return -ENODEV; + goto out; } if (!req) - return -EINVAL; + goto out; + c = p_dev->function_config; if (c->state & CONFIG_LOCKED) { dev_dbg(&s->dev, "Configuration is locked\n"); - return -EACCES; + goto out; } if (c->state & CONFIG_IO_REQ) { dev_dbg(&s->dev, "IO already configured\n"); - return -EBUSY; + goto out; } if (req->Attributes1 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS)) { dev_dbg(&s->dev, "bad attribute setting for IO region 1\n"); - return -EINVAL; + goto out; } if ((req->NumPorts2 > 0) && (req->Attributes2 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS))) { 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"); - if (alloc_io_space(s, req->Attributes1, &req->BasePort1, - req->NumPorts1, req->IOAddrLines)) { + ret = alloc_io_space(s, req->Attributes1, &req->BasePort1, + req->NumPorts1, req->IOAddrLines); + if (ret) { dev_dbg(&s->dev, "allocation of resource 1 failed\n"); - mutex_unlock(&s->ops_mutex); - return -EBUSY; + goto out; } if (req->NumPorts2) { dev_dbg(&s->dev, "trying to allocate resource 2\n"); - if (alloc_io_space(s, req->Attributes2, &req->BasePort2, - req->NumPorts2, req->IOAddrLines)) { + ret = alloc_io_space(s, req->Attributes2, &req->BasePort2, + req->NumPorts2, req->IOAddrLines); + if (ret) { dev_dbg(&s->dev, "allocation of resource 2 failed\n"); release_io_space(s, req->BasePort1, req->NumPorts1); - mutex_unlock(&s->ops_mutex); - return -EBUSY; + goto out; } } - mutex_unlock(&s->ops_mutex); c->io = *req; c->state |= CONFIG_IO_REQ; 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 */ EXPORT_SYMBOL(pcmcia_request_io); @@ -695,21 +725,22 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) int ret = -EINVAL, irq = 0; int type; + mutex_lock(&s->ops_mutex); + if (!(s->state & SOCKET_PRESENT)) { dev_dbg(&s->dev, "No card present\n"); - return -ENODEV; + goto out; } c = p_dev->function_config; if (c->state & CONFIG_LOCKED) { dev_dbg(&s->dev, "Configuration is locked\n"); - return -EACCES; + goto out; } if (c->state & CONFIG_IRQ_REQ) { 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 */ type = 0; 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) if (ret && !s->irq.AssignedIRQ) { if (!s->pci_irq) { dev_printk(KERN_INFO, &s->dev, "no IRQ found\n"); - return ret; + goto out; } type = IRQF_SHARED; irq = s->pci_irq; @@ -780,7 +811,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) if (ret) { dev_printk(KERN_INFO, &s->dev, "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) pcmcia_used_irq[irq]++; #endif + ret = 0; +out: mutex_unlock(&s->ops_mutex); - - return 0; + return ret; } /* pcmcia_request_irq */ EXPORT_SYMBOL(pcmcia_request_irq); -- cgit v1.2.3