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 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); ··· 820 } 821 822 if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) { 823 - if (dev->device_no != did->device_no) 824 - return 0; 825 mutex_lock(&dev->socket->ops_mutex); 826 dev->socket->pcmcia_state.has_pfc = 1; 827 mutex_unlock(&dev->socket->ops_mutex); 828 } 829 830 if (did->match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID) { ··· 836 837 /* if this is a pseudo-multi-function device, 838 * we need explicit matches */ 839 - if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) 840 return 0; 841 if (dev->device_no) 842 return 0; ··· 1253 1254 switch (event) { 1255 case CS_EVENT_CARD_REMOVAL: 1256 - mutex_lock(&s->ops_mutex); 1257 - s->pcmcia_state.present = 0; 1258 - mutex_unlock(&s->ops_mutex); 1259 pcmcia_card_remove(skt, NULL); 1260 handle_event(skt, event); 1261 mutex_lock(&s->ops_mutex); ··· 1262 break; 1263 1264 case CS_EVENT_CARD_INSERTION: 1265 mutex_lock(&s->ops_mutex); 1266 s->pcmcia_state.has_pfc = 0; 1267 - s->pcmcia_state.present = 1; 1268 destroy_cis_cache(s); /* to be on the safe side... */ 1269 mutex_unlock(&s->ops_mutex); 1270 pcmcia_card_add(skt); ··· 1304 return 0; 1305 } /* ds_event */ 1306 1307 - 1308 struct pcmcia_device *pcmcia_dev_present(struct pcmcia_device *_p_dev) 1309 { 1310 struct pcmcia_device *p_dev; ··· 1320 if (!p_dev) 1321 return NULL; 1322 1323 - mutex_lock(&p_dev->socket->ops_mutex); 1324 - if (!p_dev->socket->pcmcia_state.present) 1325 - goto out; 1326 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 pcmcia_put_dev(p_dev); 1340 return ret; 1341 } ··· 1372 return ret; 1373 } 1374 1375 return 0; 1376 } 1377 ··· 1384 1385 if (!socket) 1386 return; 1387 - 1388 - mutex_lock(&socket->ops_mutex); 1389 - socket->pcmcia_state.dead = 1; 1390 - mutex_unlock(&socket->ops_mutex); 1391 1392 pccard_register_pcmcia(socket, NULL); 1393
··· 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); ··· 828 } 829 830 if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) { 831 + dev_dbg(&dev->dev, "this is a pseudo-multi-function device\n"); 832 mutex_lock(&dev->socket->ops_mutex); 833 dev->socket->pcmcia_state.has_pfc = 1; 834 mutex_unlock(&dev->socket->ops_mutex); 835 + if (dev->device_no != did->device_no) 836 + return 0; 837 } 838 839 if (did->match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID) { ··· 843 844 /* if this is a pseudo-multi-function device, 845 * we need explicit matches */ 846 + if (dev->socket->pcmcia_state.has_pfc) 847 return 0; 848 if (dev->device_no) 849 return 0; ··· 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;