Merge branch 'urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia-2.6

* 'urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia-2.6:
pcmcia: fix matching rules for pseudo-multi-function cards
pcmcia: pcmcia_dev_present bugfix

+24 -45
+18 -36
drivers/pcmcia/ds.c
··· 335 335 336 336 mutex_lock(&s->ops_mutex); 337 337 list_del(&p_dev->socket_device_list); 338 - p_dev->_removed = 1; 339 338 mutex_unlock(&s->ops_mutex); 340 339 341 340 dev_dbg(&p_dev->dev, "unregistering device\n"); ··· 653 654 654 655 static void pcmcia_requery(struct pcmcia_socket *s) 655 656 { 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; 657 + int has_pfc; 664 658 665 659 if (s->functions == 0) { 666 660 pcmcia_card_add(s); ··· 820 828 } 821 829 822 830 if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) { 823 - if (dev->device_no != did->device_no) 824 - return 0; 831 + dev_dbg(&dev->dev, "this is a pseudo-multi-function device\n"); 825 832 mutex_lock(&dev->socket->ops_mutex); 826 833 dev->socket->pcmcia_state.has_pfc = 1; 827 834 mutex_unlock(&dev->socket->ops_mutex); 835 + if (dev->device_no != did->device_no) 836 + return 0; 828 837 } 829 838 830 839 if (did->match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID) { ··· 836 843 837 844 /* if this is a pseudo-multi-function device, 838 845 * we need explicit matches */ 839 - if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) 846 + if (dev->socket->pcmcia_state.has_pfc) 840 847 return 0; 841 848 if (dev->device_no) 842 849 return 0; ··· 1253 1260 1254 1261 switch (event) { 1255 1262 case CS_EVENT_CARD_REMOVAL: 1256 - mutex_lock(&s->ops_mutex); 1257 - s->pcmcia_state.present = 0; 1258 - mutex_unlock(&s->ops_mutex); 1263 + atomic_set(&skt->present, 0); 1259 1264 pcmcia_card_remove(skt, NULL); 1260 1265 handle_event(skt, event); 1261 1266 mutex_lock(&s->ops_mutex); ··· 1262 1271 break; 1263 1272 1264 1273 case CS_EVENT_CARD_INSERTION: 1274 + atomic_set(&skt->present, 1); 1265 1275 mutex_lock(&s->ops_mutex); 1266 1276 s->pcmcia_state.has_pfc = 0; 1267 - s->pcmcia_state.present = 1; 1268 1277 destroy_cis_cache(s); /* to be on the safe side... */ 1269 1278 mutex_unlock(&s->ops_mutex); 1270 1279 pcmcia_card_add(skt); ··· 1304 1313 return 0; 1305 1314 } /* ds_event */ 1306 1315 1307 - 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 + */ 1308 1323 struct pcmcia_device *pcmcia_dev_present(struct pcmcia_device *_p_dev) 1309 1324 { 1310 1325 struct pcmcia_device *p_dev; ··· 1320 1323 if (!p_dev) 1321 1324 return NULL; 1322 1325 1323 - mutex_lock(&p_dev->socket->ops_mutex); 1324 - if (!p_dev->socket->pcmcia_state.present) 1325 - goto out; 1326 + if (atomic_read(&p_dev->socket->present) != 0) 1327 + ret = p_dev; 1326 1328 1327 - if (p_dev->socket->pcmcia_state.dead) 1328 - goto out; 1329 - 1330 - if (p_dev->_removed) 1331 - goto out; 1332 - 1333 - if (p_dev->suspended) 1334 - goto out; 1335 - 1336 - ret = p_dev; 1337 - out: 1338 - mutex_unlock(&p_dev->socket->ops_mutex); 1339 1329 pcmcia_put_dev(p_dev); 1340 1330 return ret; 1341 1331 } ··· 1372 1388 return ret; 1373 1389 } 1374 1390 1391 + atomic_set(&socket->present, 0); 1392 + 1375 1393 return 0; 1376 1394 } 1377 1395 ··· 1384 1398 1385 1399 if (!socket) 1386 1400 return; 1387 - 1388 - mutex_lock(&socket->ops_mutex); 1389 - socket->pcmcia_state.dead = 1; 1390 - mutex_unlock(&socket->ops_mutex); 1391 1401 1392 1402 pccard_register_pcmcia(socket, NULL); 1393 1403
+3 -4
include/pcmcia/ds.h
··· 26 26 #ifdef __KERNEL__ 27 27 #include <linux/device.h> 28 28 #include <pcmcia/ss.h> 29 + #include <asm/atomic.h> 29 30 30 31 /* 31 32 * PCMCIA device drivers (16-bit cards only; 32-bit cards require CardBus ··· 95 94 config_req_t conf; 96 95 window_handle_t win; 97 96 98 - /* Is the device suspended, or in the process of 99 - * being removed? */ 97 + /* Is the device suspended? */ 100 98 u16 suspended:1; 101 - u16 _removed:1; 102 99 103 100 /* Flags whether io, irq, win configurations were 104 101 * requested, and whether the configuration is "locked" */ ··· 114 115 u16 has_card_id:1; 115 116 u16 has_func_id:1; 116 117 117 - u16 reserved:3; 118 + u16 reserved:4; 118 119 119 120 u8 func_id; 120 121 u16 manf_id;
+3 -5
include/pcmcia/ss.h
··· 224 224 225 225 /* 16-bit state: */ 226 226 struct { 227 - /* PCMCIA card is present in socket */ 228 - u8 present:1; 229 227 /* "master" ioctl is used */ 230 228 u8 busy:1; 231 - /* pcmcia module is being unloaded */ 232 - u8 dead:1; 233 229 /* the PCMCIA card consists of two pseudo devices */ 234 230 u8 has_pfc:1; 235 231 236 - u8 reserved:4; 232 + u8 reserved:6; 237 233 } pcmcia_state; 238 234 235 + /* non-zero if PCMCIA card is present */ 236 + atomic_t present; 239 237 240 238 #ifdef CONFIG_PCMCIA_IOCTL 241 239 struct user_info_t *user;