aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2010-01-12 15:42:51 -0500
committerDominik Brodowski <linux@dominikbrodowski.net>2010-02-17 11:48:13 -0500
commit6b8e087b86c59c3941e125738d30cf38014089e0 (patch)
tree08f77e50e5237e3bbe5e4c8f114fddc09f242628
parentc6958fdb041db6ed77f24e871dd4af5f059d1a2b (diff)
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 <w.sang@pengutronix.de> Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
-rw-r--r--drivers/pcmcia/cistpl.c6
-rw-r--r--drivers/pcmcia/cs.c1
-rw-r--r--drivers/pcmcia/pcmcia_resource.c20
-rw-r--r--drivers/pcmcia/rsrc_nonstatic.c8
-rw-r--r--include/pcmcia/ss.h2
5 files changed, 32 insertions, 5 deletions
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index 936417c3e79e..9ad66c9848e3 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -64,6 +64,7 @@ module_param(cis_width, int, 0444);
64 64
65void release_cis_mem(struct pcmcia_socket *s) 65void release_cis_mem(struct pcmcia_socket *s)
66{ 66{
67 mutex_lock(&s->ops_mutex);
67 if (s->cis_mem.flags & MAP_ACTIVE) { 68 if (s->cis_mem.flags & MAP_ACTIVE) {
68 s->cis_mem.flags &= ~MAP_ACTIVE; 69 s->cis_mem.flags &= ~MAP_ACTIVE;
69 s->ops->set_mem_map(s, &s->cis_mem); 70 s->ops->set_mem_map(s, &s->cis_mem);
@@ -75,6 +76,7 @@ void release_cis_mem(struct pcmcia_socket *s)
75 iounmap(s->cis_virt); 76 iounmap(s->cis_virt);
76 s->cis_virt = NULL; 77 s->cis_virt = NULL;
77 } 78 }
79 mutex_unlock(&s->ops_mutex);
78} 80}
79 81
80/* 82/*
@@ -88,11 +90,13 @@ set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flag
88 pccard_mem_map *mem = &s->cis_mem; 90 pccard_mem_map *mem = &s->cis_mem;
89 int ret; 91 int ret;
90 92
93 mutex_lock(&s->ops_mutex);
91 if (!(s->features & SS_CAP_STATIC_MAP) && (mem->res == NULL)) { 94 if (!(s->features & SS_CAP_STATIC_MAP) && (mem->res == NULL)) {
92 mem->res = pcmcia_find_mem_region(0, s->map_size, s->map_size, 0, s); 95 mem->res = pcmcia_find_mem_region(0, s->map_size, s->map_size, 0, s);
93 if (mem->res == NULL) { 96 if (mem->res == NULL) {
94 dev_printk(KERN_NOTICE, &s->dev, 97 dev_printk(KERN_NOTICE, &s->dev,
95 "cs: unable to map card memory!\n"); 98 "cs: unable to map card memory!\n");
99 mutex_unlock(&s->ops_mutex);
96 return NULL; 100 return NULL;
97 } 101 }
98 s->cis_virt = NULL; 102 s->cis_virt = NULL;
@@ -108,6 +112,7 @@ set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flag
108 if (ret) { 112 if (ret) {
109 iounmap(s->cis_virt); 113 iounmap(s->cis_virt);
110 s->cis_virt = NULL; 114 s->cis_virt = NULL;
115 mutex_unlock(&s->ops_mutex);
111 return NULL; 116 return NULL;
112 } 117 }
113 118
@@ -117,6 +122,7 @@ set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flag
117 s->cis_virt = ioremap(mem->static_start, s->map_size); 122 s->cis_virt = ioremap(mem->static_start, s->map_size);
118 } 123 }
119 124
125 mutex_unlock(&s->ops_mutex);
120 return s->cis_virt; 126 return s->cis_virt;
121} 127}
122 128
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 43c90f69a7a5..91aa1f284068 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -222,6 +222,7 @@ int pcmcia_register_socket(struct pcmcia_socket *socket)
222 init_completion(&socket->socket_released); 222 init_completion(&socket->socket_released);
223 init_completion(&socket->thread_done); 223 init_completion(&socket->thread_done);
224 mutex_init(&socket->skt_mutex); 224 mutex_init(&socket->skt_mutex);
225 mutex_init(&socket->ops_mutex);
225 spin_lock_init(&socket->thread_lock); 226 spin_lock_init(&socket->thread_lock);
226 227
227 if (socket->resource_ops->init) { 228 if (socket->resource_ops->init) {
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index 8ceb7abc580a..f31ba89e40d3 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,
223 memreq_t *req) 223 memreq_t *req)
224{ 224{
225 struct pcmcia_socket *s = p_dev->socket; 225 struct pcmcia_socket *s = p_dev->socket;
226 int ret;
226 227
227 wh--; 228 wh--;
228 if (wh >= MAX_WIN) 229 if (wh >= MAX_WIN)
@@ -231,12 +232,13 @@ int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t wh,
231 dev_dbg(&s->dev, "failure: requested page is zero\n"); 232 dev_dbg(&s->dev, "failure: requested page is zero\n");
232 return -EINVAL; 233 return -EINVAL;
233 } 234 }
235 mutex_lock(&s->ops_mutex);
234 s->win[wh].card_start = req->CardOffset; 236 s->win[wh].card_start = req->CardOffset;
235 if (s->ops->set_mem_map(s, &s->win[wh]) != 0) { 237 ret = s->ops->set_mem_map(s, &s->win[wh]);
236 dev_dbg(&s->dev, "failed to set_mem_map\n"); 238 if (ret)
237 return -EIO; 239 dev_warn(&s->dev, "failed to set_mem_map\n");
238 } 240 mutex_unlock(&s->ops_mutex);
239 return 0; 241 return ret;
240} /* pcmcia_map_mem_page */ 242} /* pcmcia_map_mem_page */
241EXPORT_SYMBOL(pcmcia_map_mem_page); 243EXPORT_SYMBOL(pcmcia_map_mem_page);
242 244
@@ -437,10 +439,12 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, window_handle_t wh)
437 if (wh >= MAX_WIN) 439 if (wh >= MAX_WIN)
438 return -EINVAL; 440 return -EINVAL;
439 441
442 mutex_lock(&s->ops_mutex);
440 win = &s->win[wh]; 443 win = &s->win[wh];
441 444
442 if (!(p_dev->_win & CLIENT_WIN_REQ(wh))) { 445 if (!(p_dev->_win & CLIENT_WIN_REQ(wh))) {
443 dev_dbg(&s->dev, "not releasing unknown window\n"); 446 dev_dbg(&s->dev, "not releasing unknown window\n");
447 mutex_unlock(&s->ops_mutex);
444 return -EINVAL; 448 return -EINVAL;
445 } 449 }
446 450
@@ -456,6 +460,7 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, window_handle_t wh)
456 win->res = NULL; 460 win->res = NULL;
457 } 461 }
458 p_dev->_win &= ~CLIENT_WIN_REQ(wh); 462 p_dev->_win &= ~CLIENT_WIN_REQ(wh);
463 mutex_unlock(&s->ops_mutex);
459 464
460 return 0; 465 return 0;
461} /* pcmcia_release_window */ 466} /* pcmcia_release_window */
@@ -829,6 +834,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
829 return -EINVAL; 834 return -EINVAL;
830 } 835 }
831 836
837 mutex_lock(&s->ops_mutex);
832 win = &s->win[w]; 838 win = &s->win[w];
833 839
834 if (!(s->features & SS_CAP_STATIC_MAP)) { 840 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
836 (req->Attributes & WIN_MAP_BELOW_1MB), s); 842 (req->Attributes & WIN_MAP_BELOW_1MB), s);
837 if (!win->res) { 843 if (!win->res) {
838 dev_dbg(&s->dev, "allocating mem region failed\n"); 844 dev_dbg(&s->dev, "allocating mem region failed\n");
845 mutex_unlock(&s->ops_mutex);
839 return -EINVAL; 846 return -EINVAL;
840 } 847 }
841 } 848 }
@@ -854,8 +861,10 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
854 if (req->Attributes & WIN_USE_WAIT) 861 if (req->Attributes & WIN_USE_WAIT)
855 win->flags |= MAP_USE_WAIT; 862 win->flags |= MAP_USE_WAIT;
856 win->card_start = 0; 863 win->card_start = 0;
864
857 if (s->ops->set_mem_map(s, win) != 0) { 865 if (s->ops->set_mem_map(s, win) != 0) {
858 dev_dbg(&s->dev, "failed to set memory mapping\n"); 866 dev_dbg(&s->dev, "failed to set memory mapping\n");
867 mutex_unlock(&s->ops_mutex);
859 return -EIO; 868 return -EIO;
860 } 869 }
861 s->state |= SOCKET_WIN_REQ(w); 870 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
866 else 875 else
867 req->Base = win->res->start; 876 req->Base = win->res->start;
868 877
878 mutex_unlock(&s->ops_mutex);
869 *wh = w + 1; 879 *wh = w + 1;
870 880
871 return 0; 881 return 0;
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index 91626c17f97b..1de46cf2772f 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -274,17 +274,21 @@ static int readable(struct pcmcia_socket *s, struct resource *res,
274{ 274{
275 int ret = -EINVAL; 275 int ret = -EINVAL;
276 276
277 mutex_lock(&s->ops_mutex);
277 s->cis_mem.res = res; 278 s->cis_mem.res = res;
278 s->cis_virt = ioremap(res->start, s->map_size); 279 s->cis_virt = ioremap(res->start, s->map_size);
279 if (s->cis_virt) { 280 if (s->cis_virt) {
281 mutex_unlock(&s->ops_mutex);
280 /* as we're only called from pcmcia.c, we're safe */ 282 /* as we're only called from pcmcia.c, we're safe */
281 if (s->callback->validate) 283 if (s->callback->validate)
282 ret = s->callback->validate(s, count); 284 ret = s->callback->validate(s, count);
283 /* invalidate mapping */ 285 /* invalidate mapping */
286 mutex_lock(&s->ops_mutex);
284 iounmap(s->cis_virt); 287 iounmap(s->cis_virt);
285 s->cis_virt = NULL; 288 s->cis_virt = NULL;
286 } 289 }
287 s->cis_mem.res = NULL; 290 s->cis_mem.res = NULL;
291 mutex_unlock(&s->ops_mutex);
288 if ((ret) || (*count == 0)) 292 if ((ret) || (*count == 0))
289 return -EINVAL; 293 return -EINVAL;
290 return 0; 294 return 0;
@@ -300,6 +304,8 @@ static int checksum(struct pcmcia_socket *s, struct resource *res,
300 int i, a = 0, b = -1, d; 304 int i, a = 0, b = -1, d;
301 void __iomem *virt; 305 void __iomem *virt;
302 306
307 mutex_lock(&s->ops_mutex);
308
303 virt = ioremap(res->start, s->map_size); 309 virt = ioremap(res->start, s->map_size);
304 if (virt) { 310 if (virt) {
305 map.map = 0; 311 map.map = 0;
@@ -322,6 +328,8 @@ static int checksum(struct pcmcia_socket *s, struct resource *res,
322 iounmap(virt); 328 iounmap(virt);
323 } 329 }
324 330
331 mutex_unlock(&s->ops_mutex);
332
325 if (b == -1) 333 if (b == -1)
326 return -EINVAL; 334 return -EINVAL;
327 335
diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h
index 9ab53d872489..e756069859b5 100644
--- a/include/pcmcia/ss.h
+++ b/include/pcmcia/ss.h
@@ -203,6 +203,8 @@ struct pcmcia_socket {
203 unsigned int thread_events; 203 unsigned int thread_events;
204 /* protects socket h/w state */ 204 /* protects socket h/w state */
205 struct mutex skt_mutex; 205 struct mutex skt_mutex;
206 /* protects PCMCIA state */
207 struct mutex ops_mutex;
206 /* protects thread_events */ 208 /* protects thread_events */
207 spinlock_t thread_lock; 209 spinlock_t thread_lock;
208 210