diff options
Diffstat (limited to 'drivers/pcmcia')
-rw-r--r-- | drivers/pcmcia/cs.c | 16 | ||||
-rw-r--r-- | drivers/pcmcia/db1xxx_ss.c | 16 | ||||
-rw-r--r-- | drivers/pcmcia/ds.c | 55 | ||||
-rw-r--r-- | drivers/pcmcia/pcmcia_ioctl.c | 7 |
4 files changed, 33 insertions, 61 deletions
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 75ed866e6953..c3383750e333 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c | |||
@@ -671,20 +671,22 @@ static int pccardd(void *__skt) | |||
671 | socket_remove(skt); | 671 | socket_remove(skt); |
672 | if (sysfs_events & PCMCIA_UEVENT_INSERT) | 672 | if (sysfs_events & PCMCIA_UEVENT_INSERT) |
673 | socket_insert(skt); | 673 | socket_insert(skt); |
674 | if ((sysfs_events & PCMCIA_UEVENT_RESUME) && | ||
675 | !(skt->state & SOCKET_CARDBUS)) { | ||
676 | ret = socket_resume(skt); | ||
677 | if (!ret && skt->callback) | ||
678 | skt->callback->resume(skt); | ||
679 | } | ||
680 | if ((sysfs_events & PCMCIA_UEVENT_SUSPEND) && | 674 | if ((sysfs_events & PCMCIA_UEVENT_SUSPEND) && |
681 | !(skt->state & SOCKET_CARDBUS)) { | 675 | !(skt->state & SOCKET_CARDBUS)) { |
682 | if (skt->callback) | 676 | if (skt->callback) |
683 | ret = skt->callback->suspend(skt); | 677 | ret = skt->callback->suspend(skt); |
684 | else | 678 | else |
685 | ret = 0; | 679 | ret = 0; |
686 | if (!ret) | 680 | if (!ret) { |
687 | socket_suspend(skt); | 681 | socket_suspend(skt); |
682 | msleep(100); | ||
683 | } | ||
684 | } | ||
685 | if ((sysfs_events & PCMCIA_UEVENT_RESUME) && | ||
686 | !(skt->state & SOCKET_CARDBUS)) { | ||
687 | ret = socket_resume(skt); | ||
688 | if (!ret && skt->callback) | ||
689 | skt->callback->resume(skt); | ||
688 | } | 690 | } |
689 | if ((sysfs_events & PCMCIA_UEVENT_REQUERY) && | 691 | if ((sysfs_events & PCMCIA_UEVENT_REQUERY) && |
690 | !(skt->state & SOCKET_CARDBUS)) { | 692 | !(skt->state & SOCKET_CARDBUS)) { |
diff --git a/drivers/pcmcia/db1xxx_ss.c b/drivers/pcmcia/db1xxx_ss.c index 2d48196a48cd..0f4cc3f00028 100644 --- a/drivers/pcmcia/db1xxx_ss.c +++ b/drivers/pcmcia/db1xxx_ss.c | |||
@@ -146,7 +146,6 @@ static irqreturn_t db1200_pcmcia_cdirq(int irq, void *data) | |||
146 | static int db1x_pcmcia_setup_irqs(struct db1x_pcmcia_sock *sock) | 146 | static int db1x_pcmcia_setup_irqs(struct db1x_pcmcia_sock *sock) |
147 | { | 147 | { |
148 | int ret; | 148 | int ret; |
149 | unsigned long flags; | ||
150 | 149 | ||
151 | if (sock->stschg_irq != -1) { | 150 | if (sock->stschg_irq != -1) { |
152 | ret = request_irq(sock->stschg_irq, db1000_pcmcia_stschgirq, | 151 | ret = request_irq(sock->stschg_irq, db1000_pcmcia_stschgirq, |
@@ -162,30 +161,23 @@ static int db1x_pcmcia_setup_irqs(struct db1x_pcmcia_sock *sock) | |||
162 | * active one disabled. | 161 | * active one disabled. |
163 | */ | 162 | */ |
164 | if (sock->board_type == BOARD_TYPE_DB1200) { | 163 | if (sock->board_type == BOARD_TYPE_DB1200) { |
165 | local_irq_save(flags); | ||
166 | |||
167 | ret = request_irq(sock->insert_irq, db1200_pcmcia_cdirq, | 164 | ret = request_irq(sock->insert_irq, db1200_pcmcia_cdirq, |
168 | IRQF_DISABLED, "pcmcia_insert", sock); | 165 | IRQF_DISABLED, "pcmcia_insert", sock); |
169 | if (ret) { | 166 | if (ret) |
170 | local_irq_restore(flags); | ||
171 | goto out1; | 167 | goto out1; |
172 | } | ||
173 | 168 | ||
174 | ret = request_irq(sock->eject_irq, db1200_pcmcia_cdirq, | 169 | ret = request_irq(sock->eject_irq, db1200_pcmcia_cdirq, |
175 | IRQF_DISABLED, "pcmcia_eject", sock); | 170 | IRQF_DISABLED, "pcmcia_eject", sock); |
176 | if (ret) { | 171 | if (ret) { |
177 | free_irq(sock->insert_irq, sock); | 172 | free_irq(sock->insert_irq, sock); |
178 | local_irq_restore(flags); | ||
179 | goto out1; | 173 | goto out1; |
180 | } | 174 | } |
181 | 175 | ||
182 | /* disable the currently active one */ | 176 | /* enable the currently silent one */ |
183 | if (db1200_card_inserted(sock)) | 177 | if (db1200_card_inserted(sock)) |
184 | disable_irq_nosync(sock->insert_irq); | 178 | enable_irq(sock->eject_irq); |
185 | else | 179 | else |
186 | disable_irq_nosync(sock->eject_irq); | 180 | enable_irq(sock->insert_irq); |
187 | |||
188 | local_irq_restore(flags); | ||
189 | } else { | 181 | } else { |
190 | /* all other (older) Db1x00 boards use a GPIO to show | 182 | /* all other (older) Db1x00 boards use a GPIO to show |
191 | * card detection status: use both-edge triggers. | 183 | * card detection status: use both-edge triggers. |
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 4014cf8e4a26..041eee43fd8d 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
@@ -335,7 +335,6 @@ static void pcmcia_card_remove(struct pcmcia_socket *s, struct pcmcia_device *le | |||
335 | 335 | ||
336 | mutex_lock(&s->ops_mutex); | 336 | mutex_lock(&s->ops_mutex); |
337 | list_del(&p_dev->socket_device_list); | 337 | list_del(&p_dev->socket_device_list); |
338 | p_dev->_removed = 1; | ||
339 | mutex_unlock(&s->ops_mutex); | 338 | mutex_unlock(&s->ops_mutex); |
340 | 339 | ||
341 | dev_dbg(&p_dev->dev, "unregistering device\n"); | 340 | dev_dbg(&p_dev->dev, "unregistering device\n"); |
@@ -654,14 +653,7 @@ static int pcmcia_requery_callback(struct device *dev, void * _data) | |||
654 | 653 | ||
655 | static void pcmcia_requery(struct pcmcia_socket *s) | 654 | static void pcmcia_requery(struct pcmcia_socket *s) |
656 | { | 655 | { |
657 | int present, has_pfc; | 656 | int has_pfc; |
658 | |||
659 | mutex_lock(&s->ops_mutex); | ||
660 | present = s->pcmcia_state.present; | ||
661 | mutex_unlock(&s->ops_mutex); | ||
662 | |||
663 | if (!present) | ||
664 | return; | ||
665 | 657 | ||
666 | if (s->functions == 0) { | 658 | if (s->functions == 0) { |
667 | pcmcia_card_add(s); | 659 | pcmcia_card_add(s); |
@@ -828,11 +820,12 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev, | |||
828 | } | 820 | } |
829 | 821 | ||
830 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) { | 822 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) { |
831 | if (dev->device_no != did->device_no) | 823 | dev_dbg(&dev->dev, "this is a pseudo-multi-function device\n"); |
832 | return 0; | ||
833 | mutex_lock(&dev->socket->ops_mutex); | 824 | mutex_lock(&dev->socket->ops_mutex); |
834 | dev->socket->pcmcia_state.has_pfc = 1; | 825 | dev->socket->pcmcia_state.has_pfc = 1; |
835 | mutex_unlock(&dev->socket->ops_mutex); | 826 | mutex_unlock(&dev->socket->ops_mutex); |
827 | if (dev->device_no != did->device_no) | ||
828 | return 0; | ||
836 | } | 829 | } |
837 | 830 | ||
838 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID) { | 831 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID) { |
@@ -843,7 +836,7 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev, | |||
843 | 836 | ||
844 | /* if this is a pseudo-multi-function device, | 837 | /* if this is a pseudo-multi-function device, |
845 | * we need explicit matches */ | 838 | * we need explicit matches */ |
846 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) | 839 | if (dev->socket->pcmcia_state.has_pfc) |
847 | return 0; | 840 | return 0; |
848 | if (dev->device_no) | 841 | if (dev->device_no) |
849 | return 0; | 842 | return 0; |
@@ -1260,9 +1253,7 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) | |||
1260 | 1253 | ||
1261 | switch (event) { | 1254 | switch (event) { |
1262 | case CS_EVENT_CARD_REMOVAL: | 1255 | case CS_EVENT_CARD_REMOVAL: |
1263 | mutex_lock(&s->ops_mutex); | 1256 | atomic_set(&skt->present, 0); |
1264 | s->pcmcia_state.present = 0; | ||
1265 | mutex_unlock(&s->ops_mutex); | ||
1266 | pcmcia_card_remove(skt, NULL); | 1257 | pcmcia_card_remove(skt, NULL); |
1267 | handle_event(skt, event); | 1258 | handle_event(skt, event); |
1268 | mutex_lock(&s->ops_mutex); | 1259 | mutex_lock(&s->ops_mutex); |
@@ -1271,9 +1262,9 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) | |||
1271 | break; | 1262 | break; |
1272 | 1263 | ||
1273 | case CS_EVENT_CARD_INSERTION: | 1264 | case CS_EVENT_CARD_INSERTION: |
1265 | atomic_set(&skt->present, 1); | ||
1274 | mutex_lock(&s->ops_mutex); | 1266 | mutex_lock(&s->ops_mutex); |
1275 | s->pcmcia_state.has_pfc = 0; | 1267 | s->pcmcia_state.has_pfc = 0; |
1276 | s->pcmcia_state.present = 1; | ||
1277 | destroy_cis_cache(s); /* to be on the safe side... */ | 1268 | destroy_cis_cache(s); /* to be on the safe side... */ |
1278 | mutex_unlock(&s->ops_mutex); | 1269 | mutex_unlock(&s->ops_mutex); |
1279 | pcmcia_card_add(skt); | 1270 | pcmcia_card_add(skt); |
@@ -1292,6 +1283,7 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) | |||
1292 | destroy_cis_cache(skt); | 1283 | destroy_cis_cache(skt); |
1293 | kfree(skt->fake_cis); | 1284 | kfree(skt->fake_cis); |
1294 | skt->fake_cis = NULL; | 1285 | skt->fake_cis = NULL; |
1286 | s->functions = 0; | ||
1295 | mutex_unlock(&s->ops_mutex); | 1287 | mutex_unlock(&s->ops_mutex); |
1296 | /* now, add the new card */ | 1288 | /* now, add the new card */ |
1297 | ds_event(skt, CS_EVENT_CARD_INSERTION, | 1289 | ds_event(skt, CS_EVENT_CARD_INSERTION, |
@@ -1313,7 +1305,13 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) | |||
1313 | return 0; | 1305 | return 0; |
1314 | } /* ds_event */ | 1306 | } /* ds_event */ |
1315 | 1307 | ||
1316 | 1308 | /* | |
1309 | * NOTE: This is racy. There's no guarantee the card will still be | ||
1310 | * physically present, even if the call to this function returns | ||
1311 | * non-NULL. Furthermore, the device driver most likely is unbound | ||
1312 | * almost immediately, so the timeframe where pcmcia_dev_present | ||
1313 | * returns NULL is probably really really small. | ||
1314 | */ | ||
1317 | struct pcmcia_device *pcmcia_dev_present(struct pcmcia_device *_p_dev) | 1315 | struct pcmcia_device *pcmcia_dev_present(struct pcmcia_device *_p_dev) |
1318 | { | 1316 | { |
1319 | struct pcmcia_device *p_dev; | 1317 | struct pcmcia_device *p_dev; |
@@ -1323,22 +1321,9 @@ struct pcmcia_device *pcmcia_dev_present(struct pcmcia_device *_p_dev) | |||
1323 | if (!p_dev) | 1321 | if (!p_dev) |
1324 | return NULL; | 1322 | return NULL; |
1325 | 1323 | ||
1326 | mutex_lock(&p_dev->socket->ops_mutex); | 1324 | if (atomic_read(&p_dev->socket->present) != 0) |
1327 | if (!p_dev->socket->pcmcia_state.present) | 1325 | ret = p_dev; |
1328 | goto out; | ||
1329 | |||
1330 | if (p_dev->socket->pcmcia_state.dead) | ||
1331 | goto out; | ||
1332 | 1326 | ||
1333 | if (p_dev->_removed) | ||
1334 | goto out; | ||
1335 | |||
1336 | if (p_dev->suspended) | ||
1337 | goto out; | ||
1338 | |||
1339 | ret = p_dev; | ||
1340 | out: | ||
1341 | mutex_unlock(&p_dev->socket->ops_mutex); | ||
1342 | pcmcia_put_dev(p_dev); | 1327 | pcmcia_put_dev(p_dev); |
1343 | return ret; | 1328 | return ret; |
1344 | } | 1329 | } |
@@ -1388,6 +1373,8 @@ static int __devinit pcmcia_bus_add_socket(struct device *dev, | |||
1388 | return ret; | 1373 | return ret; |
1389 | } | 1374 | } |
1390 | 1375 | ||
1376 | atomic_set(&socket->present, 0); | ||
1377 | |||
1391 | return 0; | 1378 | return 0; |
1392 | } | 1379 | } |
1393 | 1380 | ||
@@ -1399,10 +1386,6 @@ static void pcmcia_bus_remove_socket(struct device *dev, | |||
1399 | if (!socket) | 1386 | if (!socket) |
1400 | return; | 1387 | return; |
1401 | 1388 | ||
1402 | mutex_lock(&socket->ops_mutex); | ||
1403 | socket->pcmcia_state.dead = 1; | ||
1404 | mutex_unlock(&socket->ops_mutex); | ||
1405 | |||
1406 | pccard_register_pcmcia(socket, NULL); | 1389 | pccard_register_pcmcia(socket, NULL); |
1407 | 1390 | ||
1408 | /* unregister any unbound devices */ | 1391 | /* unregister any unbound devices */ |
diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c index 104e73d5d86c..7631faa0cadd 100644 --- a/drivers/pcmcia/pcmcia_ioctl.c +++ b/drivers/pcmcia/pcmcia_ioctl.c | |||
@@ -711,7 +711,7 @@ static int ds_open(struct inode *inode, struct file *file) | |||
711 | warning_printed = 1; | 711 | warning_printed = 1; |
712 | } | 712 | } |
713 | 713 | ||
714 | if (s->pcmcia_state.present) | 714 | if (atomic_read(&s->present)) |
715 | queue_event(user, CS_EVENT_CARD_INSERTION); | 715 | queue_event(user, CS_EVENT_CARD_INSERTION); |
716 | out: | 716 | out: |
717 | unlock_kernel(); | 717 | unlock_kernel(); |
@@ -770,9 +770,6 @@ static ssize_t ds_read(struct file *file, char __user *buf, | |||
770 | return -EIO; | 770 | return -EIO; |
771 | 771 | ||
772 | s = user->socket; | 772 | s = user->socket; |
773 | if (s->pcmcia_state.dead) | ||
774 | return -EIO; | ||
775 | |||
776 | ret = wait_event_interruptible(s->queue, !queue_empty(user)); | 773 | ret = wait_event_interruptible(s->queue, !queue_empty(user)); |
777 | if (ret == 0) | 774 | if (ret == 0) |
778 | ret = put_user(get_queued_event(user), (int __user *)buf) ? -EFAULT : 4; | 775 | ret = put_user(get_queued_event(user), (int __user *)buf) ? -EFAULT : 4; |
@@ -838,8 +835,6 @@ static int ds_ioctl(struct inode *inode, struct file *file, | |||
838 | return -EIO; | 835 | return -EIO; |
839 | 836 | ||
840 | s = user->socket; | 837 | s = user->socket; |
841 | if (s->pcmcia_state.dead) | ||
842 | return -EIO; | ||
843 | 838 | ||
844 | size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT; | 839 | size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT; |
845 | if (size > sizeof(ds_ioctl_arg_t)) | 840 | if (size > sizeof(ds_ioctl_arg_t)) |