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

Commit 9e86749c authored by Dominik Brodowski's avatar Dominik Brodowski
Browse files

pcmcia: lock ops->set_socket



As a side effect,
	socket_state_t			socket;
	u_int				state;
	u_int				suspended_state;
are properly protected now.

Tested-by: default avatarWolfram Sang <w.sang@pengutronix.de>
Signed-off-by: default avatarDominik Brodowski <linux@dominikbrodowski.net>
parent 8533ee31
Loading
Loading
Loading
Loading
+16 −2
Original line number Diff line number Diff line
@@ -383,6 +383,8 @@ static void socket_shutdown(struct pcmcia_socket *s)
	dev_dbg(&s->dev, "shutdown\n");

	send_event(s, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH);

	mutex_lock(&s->ops_mutex);
	s->state &= SOCKET_INUSE | SOCKET_PRESENT;
	msleep(shutdown_delay * 10);
	s->state &= SOCKET_INUSE;
@@ -410,6 +412,7 @@ static void socket_shutdown(struct pcmcia_socket *s)
	}

	s->state &= ~SOCKET_INUSE;
	mutex_unlock(&s->ops_mutex);
}

static int socket_setup(struct pcmcia_socket *skt, int initial_delay)
@@ -498,6 +501,7 @@ static int socket_insert(struct pcmcia_socket *skt)

	dev_dbg(&skt->dev, "insert\n");

	mutex_lock(&skt->ops_mutex);
	WARN_ON(skt->state & SOCKET_INUSE);
	skt->state |= SOCKET_INUSE;

@@ -517,9 +521,11 @@ static int socket_insert(struct pcmcia_socket *skt)
		}
#endif
		dev_dbg(&skt->dev, "insert done\n");
		mutex_unlock(&skt->ops_mutex);

		send_event(skt, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
	} else {
		mutex_unlock(&skt->ops_mutex);
		socket_shutdown(skt);
	}

@@ -531,6 +537,7 @@ static int socket_suspend(struct pcmcia_socket *skt)
	if (skt->state & SOCKET_SUSPEND)
		return -EBUSY;

	mutex_lock(&skt->ops_mutex);
	skt->suspended_state = skt->state;

	send_event(skt, CS_EVENT_PM_SUSPEND, CS_EVENT_PRI_LOW);
@@ -539,23 +546,27 @@ static int socket_suspend(struct pcmcia_socket *skt)
	if (skt->ops->suspend)
		skt->ops->suspend(skt);
	skt->state |= SOCKET_SUSPEND;

	mutex_unlock(&skt->ops_mutex);
	return 0;
}

static int socket_early_resume(struct pcmcia_socket *skt)
{
	mutex_lock(&skt->ops_mutex);
	skt->socket = dead_socket;
	skt->ops->init(skt);
	skt->ops->set_socket(skt, &skt->socket);
	if (skt->state & SOCKET_PRESENT)
		skt->resume_status = socket_setup(skt, resume_delay);
	mutex_unlock(&skt->ops_mutex);
	return 0;
}

static int socket_late_resume(struct pcmcia_socket *skt)
{
	mutex_lock(&skt->ops_mutex);
	skt->state &= ~SOCKET_SUSPEND;
	mutex_unlock(&skt->ops_mutex);

	if (!(skt->state & SOCKET_PRESENT))
		return socket_insert(skt);
@@ -795,7 +806,10 @@ int pcmcia_reset_card(struct pcmcia_socket *skt)
			send_event(skt, CS_EVENT_RESET_PHYSICAL, CS_EVENT_PRI_LOW);
			if (skt->callback)
				skt->callback->suspend(skt);
			if (socket_reset(skt) == 0) {
			mutex_lock(&skt->ops_mutex);
			ret = socket_reset(skt);
			mutex_unlock(&skt->ops_mutex);
			if (ret == 0) {
				send_event(skt, CS_EVENT_CARD_RESET, CS_EVENT_PRI_LOW);
				if (skt->callback)
					skt->callback->resume(skt);
+13 −2
Original line number Diff line number Diff line
@@ -266,6 +266,7 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
	}

	if (mod->Attributes & CONF_IRQ_CHANGE_VALID) {
		mutex_lock(&s->ops_mutex);
		if (mod->Attributes & CONF_ENABLE_IRQ) {
			c->Attributes |= CONF_ENABLE_IRQ;
			s->socket.io_irq = s->irq.AssignedIRQ;
@@ -274,6 +275,7 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
			s->socket.io_irq = 0;
		}
		s->ops->set_socket(s, &s->socket);
		mutex_unlock(&s->ops_mutex);
	}

	if (mod->Attributes & CONF_VCC_CHANGE_VALID) {
@@ -288,12 +290,15 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
			dev_dbg(&s->dev, "Vpp1 and Vpp2 must be the same\n");
			return -EINVAL;
		}
		mutex_lock(&s->ops_mutex);
		s->socket.Vpp = mod->Vpp1;
		if (s->ops->set_socket(s, &s->socket)) {
			mutex_unlock(&s->ops_mutex);
			dev_printk(KERN_WARNING, &s->dev,
				   "Unable to set VPP\n");
			return -EIO;
		}
		mutex_unlock(&s->ops_mutex);
	} else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) ||
		   (mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
		dev_dbg(&s->dev, "changing Vcc is not allowed at this time\n");
@@ -336,6 +341,7 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev)
	config_t *c = p_dev->function_config;
	int i;

	mutex_lock(&s->ops_mutex);
	if (p_dev->_locked) {
		p_dev->_locked = 0;
		if (--(s->lock_count) == 0) {
@@ -347,7 +353,6 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev)
	}
	if (c->state & CONFIG_LOCKED) {
		c->state &= ~CONFIG_LOCKED;
		mutex_lock(&s->ops_mutex);
		if (c->state & CONFIG_IO_REQ)
			for (i = 0; i < MAX_IO_WIN; i++) {
				if (!s->io[i].res)
@@ -358,8 +363,8 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev)
				io.map = i;
				s->ops->set_io_map(s, &io);
			}
		mutex_unlock(&s->ops_mutex);
	}
	mutex_unlock(&s->ops_mutex);

	return 0;
} /* pcmcia_release_configuration */
@@ -493,9 +498,11 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
		return -EACCES;
	}

	mutex_lock(&s->ops_mutex);
	/* Do power control.  We don't allow changes in Vcc. */
	s->socket.Vpp = req->Vpp;
	if (s->ops->set_socket(s, &s->socket)) {
		mutex_unlock(&s->ops_mutex);
		dev_printk(KERN_WARNING, &s->dev,
			   "Unable to set socket state\n");
		return -EINVAL;
@@ -518,6 +525,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
		s->socket.io_irq = 0;
	s->ops->set_socket(s, &s->socket);
	s->lock_count++;
	mutex_unlock(&s->ops_mutex);

	/* Set up CIS configuration registers */
	base = c->ConfigBase = req->ConfigBase;
@@ -698,6 +706,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
		return -EBUSY;
	}

	mutex_lock(&s->ops_mutex);
	/* Decide what type of interrupt we are registering */
	type = 0;
	if (s->functions > 1)		/* All of this ought to be handled higher up */
@@ -791,6 +800,8 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
	pcmcia_used_irq[irq]++;
#endif

	mutex_unlock(&s->ops_mutex);

	return 0;
} /* pcmcia_request_irq */
EXPORT_SYMBOL(pcmcia_request_irq);