aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia/cistpl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pcmcia/cistpl.c')
-rw-r--r--drivers/pcmcia/cistpl.c18
1 files changed, 17 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