pcmcia: pcmcia_dev_present bugfix

pcmcia_dev_present is in and by itself buggy. Add a note specifying
why it is broken, and replace the broken locking -- taking a mutex
is a bad idea in IRQ context, from which this function is rarely
called -- by an atomic_t.

Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>

+20 -42
+14 -33
drivers/pcmcia/ds.c
··· 335 336 mutex_lock(&s->ops_mutex); 337 list_del(&p_dev->socket_device_list); 338 - p_dev->_removed = 1; 339 mutex_unlock(&s->ops_mutex); 340 341 dev_dbg(&p_dev->dev, "unregistering device\n"); ··· 653 654 static void pcmcia_requery(struct pcmcia_socket *s) 655 { 656 - int present, has_pfc; 657 - 658 - mutex_lock(&s->ops_mutex); 659 - present = s->pcmcia_state.present; 660 - mutex_unlock(&s->ops_mutex); 661 - 662 - if (!present) 663 - return; 664 665 if (s->functions == 0) { 666 pcmcia_card_add(s); ··· 1252 1253 switch (event) { 1254 case CS_EVENT_CARD_REMOVAL: 1255 - mutex_lock(&s->ops_mutex); 1256 - s->pcmcia_state.present = 0; 1257 - mutex_unlock(&s->ops_mutex); 1258 pcmcia_card_remove(skt, NULL); 1259 handle_event(skt, event); 1260 mutex_lock(&s->ops_mutex); ··· 1261 break; 1262 1263 case CS_EVENT_CARD_INSERTION: 1264 mutex_lock(&s->ops_mutex); 1265 s->pcmcia_state.has_pfc = 0; 1266 - s->pcmcia_state.present = 1; 1267 destroy_cis_cache(s); /* to be on the safe side... */ 1268 mutex_unlock(&s->ops_mutex); 1269 pcmcia_card_add(skt); ··· 1303 return 0; 1304 } /* ds_event */ 1305 1306 - 1307 struct pcmcia_device *pcmcia_dev_present(struct pcmcia_device *_p_dev) 1308 { 1309 struct pcmcia_device *p_dev; ··· 1319 if (!p_dev) 1320 return NULL; 1321 1322 - mutex_lock(&p_dev->socket->ops_mutex); 1323 - if (!p_dev->socket->pcmcia_state.present) 1324 - goto out; 1325 1326 - if (p_dev->socket->pcmcia_state.dead) 1327 - goto out; 1328 - 1329 - if (p_dev->_removed) 1330 - goto out; 1331 - 1332 - if (p_dev->suspended) 1333 - goto out; 1334 - 1335 - ret = p_dev; 1336 - out: 1337 - mutex_unlock(&p_dev->socket->ops_mutex); 1338 pcmcia_put_dev(p_dev); 1339 return ret; 1340 } ··· 1371 return ret; 1372 } 1373 1374 return 0; 1375 } 1376 ··· 1383 1384 if (!socket) 1385 return; 1386 - 1387 - mutex_lock(&socket->ops_mutex); 1388 - socket->pcmcia_state.dead = 1; 1389 - mutex_unlock(&socket->ops_mutex); 1390 1391 pccard_register_pcmcia(socket, NULL); 1392
··· 335 336 mutex_lock(&s->ops_mutex); 337 list_del(&p_dev->socket_device_list); 338 mutex_unlock(&s->ops_mutex); 339 340 dev_dbg(&p_dev->dev, "unregistering device\n"); ··· 654 655 static void pcmcia_requery(struct pcmcia_socket *s) 656 { 657 + int has_pfc; 658 659 if (s->functions == 0) { 660 pcmcia_card_add(s); ··· 1260 1261 switch (event) { 1262 case CS_EVENT_CARD_REMOVAL: 1263 + atomic_set(&skt->present, 0); 1264 pcmcia_card_remove(skt, NULL); 1265 handle_event(skt, event); 1266 mutex_lock(&s->ops_mutex); ··· 1271 break; 1272 1273 case CS_EVENT_CARD_INSERTION: 1274 + atomic_set(&skt->present, 1); 1275 mutex_lock(&s->ops_mutex); 1276 s->pcmcia_state.has_pfc = 0; 1277 destroy_cis_cache(s); /* to be on the safe side... */ 1278 mutex_unlock(&s->ops_mutex); 1279 pcmcia_card_add(skt); ··· 1313 return 0; 1314 } /* ds_event */ 1315 1316 + /* 1317 + * NOTE: This is racy. There's no guarantee the card will still be 1318 + * physically present, even if the call to this function returns 1319 + * non-NULL. Furthermore, the device driver most likely is unbound 1320 + * almost immediately, so the timeframe where pcmcia_dev_present 1321 + * returns NULL is probably really really small. 1322 + */ 1323 struct pcmcia_device *pcmcia_dev_present(struct pcmcia_device *_p_dev) 1324 { 1325 struct pcmcia_device *p_dev; ··· 1323 if (!p_dev) 1324 return NULL; 1325 1326 + if (atomic_read(&p_dev->socket->present) != 0) 1327 + ret = p_dev; 1328 1329 pcmcia_put_dev(p_dev); 1330 return ret; 1331 } ··· 1388 return ret; 1389 } 1390 1391 + atomic_set(&socket->present, 0); 1392 + 1393 return 0; 1394 } 1395 ··· 1398 1399 if (!socket) 1400 return; 1401 1402 pccard_register_pcmcia(socket, NULL); 1403
+3 -4
include/pcmcia/ds.h
··· 26 #ifdef __KERNEL__ 27 #include <linux/device.h> 28 #include <pcmcia/ss.h> 29 30 /* 31 * PCMCIA device drivers (16-bit cards only; 32-bit cards require CardBus ··· 95 config_req_t conf; 96 window_handle_t win; 97 98 - /* Is the device suspended, or in the process of 99 - * being removed? */ 100 u16 suspended:1; 101 - u16 _removed:1; 102 103 /* Flags whether io, irq, win configurations were 104 * requested, and whether the configuration is "locked" */ ··· 114 u16 has_card_id:1; 115 u16 has_func_id:1; 116 117 - u16 reserved:3; 118 119 u8 func_id; 120 u16 manf_id;
··· 26 #ifdef __KERNEL__ 27 #include <linux/device.h> 28 #include <pcmcia/ss.h> 29 + #include <asm/atomic.h> 30 31 /* 32 * PCMCIA device drivers (16-bit cards only; 32-bit cards require CardBus ··· 94 config_req_t conf; 95 window_handle_t win; 96 97 + /* Is the device suspended? */ 98 u16 suspended:1; 99 100 /* Flags whether io, irq, win configurations were 101 * requested, and whether the configuration is "locked" */ ··· 115 u16 has_card_id:1; 116 u16 has_func_id:1; 117 118 + u16 reserved:4; 119 120 u8 func_id; 121 u16 manf_id;
+3 -5
include/pcmcia/ss.h
··· 224 225 /* 16-bit state: */ 226 struct { 227 - /* PCMCIA card is present in socket */ 228 - u8 present:1; 229 /* "master" ioctl is used */ 230 u8 busy:1; 231 - /* pcmcia module is being unloaded */ 232 - u8 dead:1; 233 /* the PCMCIA card consists of two pseudo devices */ 234 u8 has_pfc:1; 235 236 - u8 reserved:4; 237 } pcmcia_state; 238 239 240 #ifdef CONFIG_PCMCIA_IOCTL 241 struct user_info_t *user;
··· 224 225 /* 16-bit state: */ 226 struct { 227 /* "master" ioctl is used */ 228 u8 busy:1; 229 /* the PCMCIA card consists of two pseudo devices */ 230 u8 has_pfc:1; 231 232 + u8 reserved:6; 233 } pcmcia_state; 234 235 + /* non-zero if PCMCIA card is present */ 236 + atomic_t present; 237 238 #ifdef CONFIG_PCMCIA_IOCTL 239 struct user_info_t *user;