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

Commit c533120b authored by Alan Cox's avatar Alan Cox Committed by Dominik Brodowski
Browse files

[PATCH] pcmcia: warn if driver requests exclusive, but gets a shared IRQ



The patch below cleans up the pcmcia code a bit on the IRQ side (I did
this while debugging the problem just so I could read wtf it was doing),
and also adds a warning and passes back the correct information when a
device asks for exclusive but gets given shared. This at least means the
dmesg dump of a problem triggered by this will have a signature to find.

Signed-off-by: default avatarAlan Cox <alan@redhat.com>
Signed-off-by: default avatarDominik Brodowski <linux@dominikbrodowski.net>
parent d29693bf
Loading
Loading
Loading
Loading
+18 −9
Original line number Diff line number Diff line
@@ -788,6 +788,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
	struct pcmcia_socket *s = p_dev->socket;
	config_t *c;
	int ret = CS_IN_USE, irq = 0;
	int type;

	if (!(s->state & SOCKET_PRESENT))
		return CS_NO_CARD;
@@ -797,6 +798,13 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
	if (c->state & CONFIG_IRQ_REQ)
		return CS_IN_USE;

	/* Decide what type of interrupt we are registering */
	type = 0;
	if (s->functions > 1)		/* All of this ought to be handled higher up */
		type = SA_SHIRQ;
	if (req->Attributes & IRQ_TYPE_DYNAMIC_SHARING)
		type = SA_SHIRQ;

#ifdef CONFIG_PCMCIA_PROBE
	if (s->irq.AssignedIRQ != 0) {
		/* If the interrupt is already assigned, it must be the same */
@@ -822,9 +830,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
			 * marked as used by the kernel resource management core */
			ret = request_irq(irq,
					  (req->Attributes & IRQ_HANDLE_PRESENT) ? req->Handler : test_action,
					  ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) ||
					   (s->functions > 1) ||
					   (irq == s->pci_irq)) ? SA_SHIRQ : 0,
					  type,
					  p_dev->devname,
					  (req->Attributes & IRQ_HANDLE_PRESENT) ? req->Instance : data);
			if (!ret) {
@@ -839,18 +845,21 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
	if (ret && !s->irq.AssignedIRQ) {
		if (!s->pci_irq)
			return ret;
		type = SA_SHIRQ;
		irq = s->pci_irq;
	}

	if (ret && req->Attributes & IRQ_HANDLE_PRESENT) {
		if (request_irq(irq, req->Handler,
				((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) ||
				 (s->functions > 1) ||
				 (irq == s->pci_irq)) ? SA_SHIRQ : 0,
				p_dev->devname, req->Instance))
	if (ret && (req->Attributes & IRQ_HANDLE_PRESENT)) {
		if (request_irq(irq, req->Handler, type,  p_dev->devname, req->Instance))
			return CS_IN_USE;
	}

	/* Make sure the fact the request type was overridden is passed back */
	if (type == SA_SHIRQ && !(req->Attributes & IRQ_TYPE_DYNAMIC_SHARING)) {
		req->Attributes |= IRQ_TYPE_DYNAMIC_SHARING;
		printk(KERN_WARNING "pcmcia: request for exclusive IRQ could not be fulfilled.\n");
		printk(KERN_WARNING "pcmcia: the driver needs updating to supported shared IRQ lines.\n");
	}
	c->irq.Attributes = req->Attributes;
	s->irq.AssignedIRQ = req->AssignedIRQ = irq;
	s->irq.Config++;