Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3fb938b2 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* '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
parents 970b0648 83bf6f11
Loading
Loading
Loading
Loading
+18 −36
Original line number Original line Diff line number Diff line
@@ -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)
		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;
		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 */
+3 −4
Original line number Original line Diff line number Diff line
@@ -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;
+3 −5
Original line number Original line Diff line number Diff line
@@ -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;