diff options
-rw-r--r-- | drivers/pcmcia/cistpl.c | 18 | ||||
-rw-r--r-- | drivers/pcmcia/ds.c | 6 |
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 | ||
330 | void destroy_cis_cache(struct pcmcia_socket *s) | 339 | void 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) | |||
1518 | done: | 1532 | done: |
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); |