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
This commit is contained in:
commit
3fb938b2a8
@ -335,7 +335,6 @@ static void pcmcia_card_remove(struct pcmcia_socket *s, struct pcmcia_device *le
|
|||||||
|
|
||||||
mutex_lock(&s->ops_mutex);
|
mutex_lock(&s->ops_mutex);
|
||||||
list_del(&p_dev->socket_device_list);
|
list_del(&p_dev->socket_device_list);
|
||||||
p_dev->_removed = 1;
|
|
||||||
mutex_unlock(&s->ops_mutex);
|
mutex_unlock(&s->ops_mutex);
|
||||||
|
|
||||||
dev_dbg(&p_dev->dev, "unregistering device\n");
|
dev_dbg(&p_dev->dev, "unregistering device\n");
|
||||||
@ -654,14 +653,7 @@ static int pcmcia_requery_callback(struct device *dev, void * _data)
|
|||||||
|
|
||||||
static void pcmcia_requery(struct pcmcia_socket *s)
|
static void pcmcia_requery(struct pcmcia_socket *s)
|
||||||
{
|
{
|
||||||
int present, has_pfc;
|
int has_pfc;
|
||||||
|
|
||||||
mutex_lock(&s->ops_mutex);
|
|
||||||
present = s->pcmcia_state.present;
|
|
||||||
mutex_unlock(&s->ops_mutex);
|
|
||||||
|
|
||||||
if (!present)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (s->functions == 0) {
|
if (s->functions == 0) {
|
||||||
pcmcia_card_add(s);
|
pcmcia_card_add(s);
|
||||||
@ -828,11 +820,12 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) {
|
if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) {
|
||||||
if (dev->device_no != did->device_no)
|
dev_dbg(&dev->dev, "this is a pseudo-multi-function device\n");
|
||||||
return 0;
|
|
||||||
mutex_lock(&dev->socket->ops_mutex);
|
mutex_lock(&dev->socket->ops_mutex);
|
||||||
dev->socket->pcmcia_state.has_pfc = 1;
|
dev->socket->pcmcia_state.has_pfc = 1;
|
||||||
mutex_unlock(&dev->socket->ops_mutex);
|
mutex_unlock(&dev->socket->ops_mutex);
|
||||||
|
if (dev->device_no != did->device_no)
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (did->match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID) {
|
if (did->match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID) {
|
||||||
@ -843,7 +836,7 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev,
|
|||||||
|
|
||||||
/* if this is a pseudo-multi-function device,
|
/* if this is a pseudo-multi-function device,
|
||||||
* we need explicit matches */
|
* we need explicit matches */
|
||||||
if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO)
|
if (dev->socket->pcmcia_state.has_pfc)
|
||||||
return 0;
|
return 0;
|
||||||
if (dev->device_no)
|
if (dev->device_no)
|
||||||
return 0;
|
return 0;
|
||||||
@ -1260,9 +1253,7 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
|
|||||||
|
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case CS_EVENT_CARD_REMOVAL:
|
case CS_EVENT_CARD_REMOVAL:
|
||||||
mutex_lock(&s->ops_mutex);
|
atomic_set(&skt->present, 0);
|
||||||
s->pcmcia_state.present = 0;
|
|
||||||
mutex_unlock(&s->ops_mutex);
|
|
||||||
pcmcia_card_remove(skt, NULL);
|
pcmcia_card_remove(skt, NULL);
|
||||||
handle_event(skt, event);
|
handle_event(skt, event);
|
||||||
mutex_lock(&s->ops_mutex);
|
mutex_lock(&s->ops_mutex);
|
||||||
@ -1271,9 +1262,9 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CS_EVENT_CARD_INSERTION:
|
case CS_EVENT_CARD_INSERTION:
|
||||||
|
atomic_set(&skt->present, 1);
|
||||||
mutex_lock(&s->ops_mutex);
|
mutex_lock(&s->ops_mutex);
|
||||||
s->pcmcia_state.has_pfc = 0;
|
s->pcmcia_state.has_pfc = 0;
|
||||||
s->pcmcia_state.present = 1;
|
|
||||||
destroy_cis_cache(s); /* to be on the safe side... */
|
destroy_cis_cache(s); /* to be on the safe side... */
|
||||||
mutex_unlock(&s->ops_mutex);
|
mutex_unlock(&s->ops_mutex);
|
||||||
pcmcia_card_add(skt);
|
pcmcia_card_add(skt);
|
||||||
@ -1313,7 +1304,13 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
|
|||||||
return 0;
|
return 0;
|
||||||
} /* ds_event */
|
} /* ds_event */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: This is racy. There's no guarantee the card will still be
|
||||||
|
* physically present, even if the call to this function returns
|
||||||
|
* non-NULL. Furthermore, the device driver most likely is unbound
|
||||||
|
* almost immediately, so the timeframe where pcmcia_dev_present
|
||||||
|
* returns NULL is probably really really small.
|
||||||
|
*/
|
||||||
struct pcmcia_device *pcmcia_dev_present(struct pcmcia_device *_p_dev)
|
struct pcmcia_device *pcmcia_dev_present(struct pcmcia_device *_p_dev)
|
||||||
{
|
{
|
||||||
struct pcmcia_device *p_dev;
|
struct pcmcia_device *p_dev;
|
||||||
@ -1323,22 +1320,9 @@ struct pcmcia_device *pcmcia_dev_present(struct pcmcia_device *_p_dev)
|
|||||||
if (!p_dev)
|
if (!p_dev)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
mutex_lock(&p_dev->socket->ops_mutex);
|
if (atomic_read(&p_dev->socket->present) != 0)
|
||||||
if (!p_dev->socket->pcmcia_state.present)
|
ret = p_dev;
|
||||||
goto out;
|
|
||||||
|
|
||||||
if (p_dev->socket->pcmcia_state.dead)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
if (p_dev->_removed)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
if (p_dev->suspended)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
ret = p_dev;
|
|
||||||
out:
|
|
||||||
mutex_unlock(&p_dev->socket->ops_mutex);
|
|
||||||
pcmcia_put_dev(p_dev);
|
pcmcia_put_dev(p_dev);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -1388,6 +1372,8 @@ static int __devinit pcmcia_bus_add_socket(struct device *dev,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
atomic_set(&socket->present, 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1399,10 +1385,6 @@ static void pcmcia_bus_remove_socket(struct device *dev,
|
|||||||
if (!socket)
|
if (!socket)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mutex_lock(&socket->ops_mutex);
|
|
||||||
socket->pcmcia_state.dead = 1;
|
|
||||||
mutex_unlock(&socket->ops_mutex);
|
|
||||||
|
|
||||||
pccard_register_pcmcia(socket, NULL);
|
pccard_register_pcmcia(socket, NULL);
|
||||||
|
|
||||||
/* unregister any unbound devices */
|
/* unregister any unbound devices */
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <pcmcia/ss.h>
|
#include <pcmcia/ss.h>
|
||||||
|
#include <asm/atomic.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PCMCIA device drivers (16-bit cards only; 32-bit cards require CardBus
|
* PCMCIA device drivers (16-bit cards only; 32-bit cards require CardBus
|
||||||
@ -94,10 +95,8 @@ struct pcmcia_device {
|
|||||||
config_req_t conf;
|
config_req_t conf;
|
||||||
window_handle_t win;
|
window_handle_t win;
|
||||||
|
|
||||||
/* Is the device suspended, or in the process of
|
/* Is the device suspended? */
|
||||||
* being removed? */
|
|
||||||
u16 suspended:1;
|
u16 suspended:1;
|
||||||
u16 _removed:1;
|
|
||||||
|
|
||||||
/* Flags whether io, irq, win configurations were
|
/* Flags whether io, irq, win configurations were
|
||||||
* requested, and whether the configuration is "locked" */
|
* requested, and whether the configuration is "locked" */
|
||||||
@ -115,7 +114,7 @@ struct pcmcia_device {
|
|||||||
u16 has_card_id:1;
|
u16 has_card_id:1;
|
||||||
u16 has_func_id:1;
|
u16 has_func_id:1;
|
||||||
|
|
||||||
u16 reserved:3;
|
u16 reserved:4;
|
||||||
|
|
||||||
u8 func_id;
|
u8 func_id;
|
||||||
u16 manf_id;
|
u16 manf_id;
|
||||||
|
@ -224,18 +224,16 @@ struct pcmcia_socket {
|
|||||||
|
|
||||||
/* 16-bit state: */
|
/* 16-bit state: */
|
||||||
struct {
|
struct {
|
||||||
/* PCMCIA card is present in socket */
|
|
||||||
u8 present:1;
|
|
||||||
/* "master" ioctl is used */
|
/* "master" ioctl is used */
|
||||||
u8 busy:1;
|
u8 busy:1;
|
||||||
/* pcmcia module is being unloaded */
|
|
||||||
u8 dead:1;
|
|
||||||
/* the PCMCIA card consists of two pseudo devices */
|
/* the PCMCIA card consists of two pseudo devices */
|
||||||
u8 has_pfc:1;
|
u8 has_pfc:1;
|
||||||
|
|
||||||
u8 reserved:4;
|
u8 reserved:6;
|
||||||
} pcmcia_state;
|
} pcmcia_state;
|
||||||
|
|
||||||
|
/* non-zero if PCMCIA card is present */
|
||||||
|
atomic_t present;
|
||||||
|
|
||||||
#ifdef CONFIG_PCMCIA_IOCTL
|
#ifdef CONFIG_PCMCIA_IOCTL
|
||||||
struct user_info_t *user;
|
struct user_info_t *user;
|
||||||
|
Loading…
Reference in New Issue
Block a user