aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2010-01-12 16:05:36 -0500
committerDominik Brodowski <linux@dominikbrodowski.net>2010-02-17 11:48:14 -0500
commit8680c4b3faa298dc768c2a78a94a84d89854eca9 (patch)
treefe6faa7b62cf52ce8823027e833d946d11523e4a /drivers
parent6b8e087b86c59c3941e125738d30cf38014089e0 (diff)
pcmcia: also lock fake and cache CIS by ops_mutex
Specifically, struct list_head cis_cache; size_t fake_cis_len; u8 *fake_cis; are protected. Tested-by: Wolfram Sang <w.sang@pengutronix.de> Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/pcmcia/cistpl.c18
-rw-r--r--drivers/pcmcia/ds.c6
2 files changed, 23 insertions, 1 deletions
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index 9ad66c9848e3..14de287a8bf6 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -277,20 +277,24 @@ static void read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr,
277 if (s->state & SOCKET_CARDBUS) 277 if (s->state & SOCKET_CARDBUS)
278 return; 278 return;
279 279
280 mutex_lock(&s->ops_mutex);
280 if (s->fake_cis) { 281 if (s->fake_cis) {
281 if (s->fake_cis_len >= addr+len) 282 if (s->fake_cis_len >= addr+len)
282 memcpy(ptr, s->fake_cis+addr, len); 283 memcpy(ptr, s->fake_cis+addr, len);
283 else 284 else
284 memset(ptr, 0xff, len); 285 memset(ptr, 0xff, len);
286 mutex_unlock(&s->ops_mutex);
285 return; 287 return;
286 } 288 }
287 289
288 list_for_each_entry(cis, &s->cis_cache, node) { 290 list_for_each_entry(cis, &s->cis_cache, node) {
289 if (cis->addr == addr && cis->len == len && cis->attr == attr) { 291 if (cis->addr == addr && cis->len == len && cis->attr == attr) {
290 memcpy(ptr, cis->cache, len); 292 memcpy(ptr, cis->cache, len);
293 mutex_unlock(&s->ops_mutex);
291 return; 294 return;
292 } 295 }
293 } 296 }
297 mutex_unlock(&s->ops_mutex);
294 298
295 ret = pcmcia_read_cis_mem(s, attr, addr, len, ptr); 299 ret = pcmcia_read_cis_mem(s, attr, addr, len, ptr);
296 300
@@ -302,7 +306,9 @@ static void read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr,
302 cis->len = len; 306 cis->len = len;
303 cis->attr = attr; 307 cis->attr = attr;
304 memcpy(cis->cache, ptr, len); 308 memcpy(cis->cache, ptr, len);
309 mutex_lock(&s->ops_mutex);
305 list_add(&cis->node, &s->cis_cache); 310 list_add(&cis->node, &s->cis_cache);
311 mutex_unlock(&s->ops_mutex);
306 } 312 }
307 } 313 }
308} 314}
@@ -312,19 +318,22 @@ remove_cis_cache(struct pcmcia_socket *s, int attr, u_int addr, u_int len)
312{ 318{
313 struct cis_cache_entry *cis; 319 struct cis_cache_entry *cis;
314 320
321 mutex_lock(&s->ops_mutex);
315 list_for_each_entry(cis, &s->cis_cache, node) 322 list_for_each_entry(cis, &s->cis_cache, node)
316 if (cis->addr == addr && cis->len == len && cis->attr == attr) { 323 if (cis->addr == addr && cis->len == len && cis->attr == attr) {
317 list_del(&cis->node); 324 list_del(&cis->node);
318 kfree(cis); 325 kfree(cis);
319 break; 326 break;
320 } 327 }
328 mutex_unlock(&s->ops_mutex);
321} 329}
322 330
323/** 331/**
324 * destroy_cis_cache() - destroy the CIS cache 332 * destroy_cis_cache() - destroy the CIS cache
325 * @s: pcmcia_socket for which CIS cache shall be destroyed 333 * @s: pcmcia_socket for which CIS cache shall be destroyed
326 * 334 *
327 * This destroys the CIS cache but keeps any fake CIS alive. 335 * This destroys the CIS cache but keeps any fake CIS alive. Must be
336 * called with ops_mutex held.
328 */ 337 */
329 338
330void destroy_cis_cache(struct pcmcia_socket *s) 339void destroy_cis_cache(struct pcmcia_socket *s)
@@ -391,14 +400,17 @@ int pcmcia_replace_cis(struct pcmcia_socket *s,
391 dev_printk(KERN_WARNING, &s->dev, "replacement CIS too big\n"); 400 dev_printk(KERN_WARNING, &s->dev, "replacement CIS too big\n");
392 return -EINVAL; 401 return -EINVAL;
393 } 402 }
403 mutex_lock(&s->ops_mutex);
394 kfree(s->fake_cis); 404 kfree(s->fake_cis);
395 s->fake_cis = kmalloc(len, GFP_KERNEL); 405 s->fake_cis = kmalloc(len, GFP_KERNEL);
396 if (s->fake_cis == NULL) { 406 if (s->fake_cis == NULL) {
397 dev_printk(KERN_WARNING, &s->dev, "no memory to replace CIS\n"); 407 dev_printk(KERN_WARNING, &s->dev, "no memory to replace CIS\n");
408 mutex_unlock(&s->ops_mutex);
398 return -ENOMEM; 409 return -ENOMEM;
399 } 410 }
400 s->fake_cis_len = len; 411 s->fake_cis_len = len;
401 memcpy(s->fake_cis, data, len); 412 memcpy(s->fake_cis, data, len);
413 mutex_unlock(&s->ops_mutex);
402 return 0; 414 return 0;
403} 415}
404 416
@@ -1461,7 +1473,9 @@ int pccard_validate_cis(struct pcmcia_socket *s, unsigned int *info)
1461 return -EINVAL; 1473 return -EINVAL;
1462 1474
1463 /* We do not want to validate the CIS cache... */ 1475 /* We do not want to validate the CIS cache... */
1476 mutex_lock(&s->ops_mutex);
1464 destroy_cis_cache(s); 1477 destroy_cis_cache(s);
1478 mutex_unlock(&s->ops_mutex);
1465 1479
1466 tuple = kmalloc(sizeof(*tuple), GFP_KERNEL); 1480 tuple = kmalloc(sizeof(*tuple), GFP_KERNEL);
1467 if (tuple == NULL) { 1481 if (tuple == NULL) {
@@ -1518,7 +1532,9 @@ int pccard_validate_cis(struct pcmcia_socket *s, unsigned int *info)
1518done: 1532done:
1519 /* invalidate CIS cache on failure */ 1533 /* invalidate CIS cache on failure */
1520 if (!dev_ok || !ident_ok || !count) { 1534 if (!dev_ok || !ident_ok || !count) {
1535 mutex_lock(&s->ops_mutex);
1521 destroy_cis_cache(s); 1536 destroy_cis_cache(s);
1537 mutex_unlock(&s->ops_mutex);
1522 ret = -EIO; 1538 ret = -EIO;
1523 } 1539 }
1524 1540
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 0ab4fe045920..4f7308df22c8 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -1241,12 +1241,16 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
1241 s->pcmcia_state.present = 0; 1241 s->pcmcia_state.present = 0;
1242 pcmcia_card_remove(skt, NULL); 1242 pcmcia_card_remove(skt, NULL);
1243 handle_event(skt, event); 1243 handle_event(skt, event);
1244 mutex_lock(&s->ops_mutex);
1244 destroy_cis_cache(s); 1245 destroy_cis_cache(s);
1246 mutex_unlock(&s->ops_mutex);
1245 break; 1247 break;
1246 1248
1247 case CS_EVENT_CARD_INSERTION: 1249 case CS_EVENT_CARD_INSERTION:
1248 s->pcmcia_state.present = 1; 1250 s->pcmcia_state.present = 1;
1251 mutex_lock(&s->ops_mutex);
1249 destroy_cis_cache(s); /* to be on the safe side... */ 1252 destroy_cis_cache(s); /* to be on the safe side... */
1253 mutex_unlock(&s->ops_mutex);
1250 pcmcia_card_add(skt); 1254 pcmcia_card_add(skt);
1251 handle_event(skt, event); 1255 handle_event(skt, event);
1252 break; 1256 break;
@@ -1259,9 +1263,11 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
1259 dev_dbg(&skt->dev, "cis mismatch - different card\n"); 1263 dev_dbg(&skt->dev, "cis mismatch - different card\n");
1260 /* first, remove the card */ 1264 /* first, remove the card */
1261 ds_event(skt, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH); 1265 ds_event(skt, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH);
1266 mutex_lock(&s->ops_mutex);
1262 destroy_cis_cache(skt); 1267 destroy_cis_cache(skt);
1263 kfree(skt->fake_cis); 1268 kfree(skt->fake_cis);
1264 skt->fake_cis = NULL; 1269 skt->fake_cis = NULL;
1270 mutex_unlock(&s->ops_mutex);
1265 /* now, add the new card */ 1271 /* now, add the new card */
1266 ds_event(skt, CS_EVENT_CARD_INSERTION, 1272 ds_event(skt, CS_EVENT_CARD_INSERTION,
1267 CS_EVENT_PRI_LOW); 1273 CS_EVENT_PRI_LOW);