linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Martin Diehl <mdiehlcs@compuserve.de>
To: Linus Torvalds <torvalds@transmeta.com>
Cc: Martin Mares <mj@suse.cz>,
	Kernel Mailing List <linux-kernel@vger.kernel.org>
Subject: [PATCH] yenta, pm - part 1
Date: Mon, 18 Dec 2000 14:08:25 +0100 (CET)	[thread overview]
Message-ID: <Pine.LNX.4.21.0012181325370.579-100000@notebook.diehl.home> (raw)
In-Reply-To: <Pine.LNX.4.10.10012151042170.2255-100000@penguin.transmeta.com>

On Fri, 15 Dec 2000, Linus Torvalds wrote:

> I suspect that the suspend/resume will do something bad to the BAT
> registers, which control the BIOS area mapping behaviour, and it just
> kills the forwarding of the legacy region to the PCI bus, or something.

FYI: I've identified a single byte in the hostbridges config space which
is altered after resume. Blindly restoring it makes the 0xe6000 pci bus
address mapping accessible again. But I think that's not the Right way to
fix it.

> I wonder if the PCI cardbus init code should just notice this, and force
> all cardbus windows to be re-initialized. That legacy area address really
> doesn't look right.

That's what I've done now. So I'm sending the modification I made in case
you would still like them for 2.4.0. I've separated it in 2 (almost
independent) patches meant to be applied in series against 2.4.0-t12 (final)

This is part 1. It provides:

- pm_state, pm_lock for cardbus socket to prevent multiple suspend/resume,
  especially the reentrant case due to some driver sleeping in resume.
- cardbus_change_pm_state() to handle pm state transition. Suspend is
  handled synchronously but resume schedules an asynchronous completion
  handler since pcmcia_resume_socket() may sleep.
- placing the pci_set_power_state() calls at the right place

Mainly touching pci_socket.* it fixes the suspend/resume multiple entrance
issues due to some driver (notably cardbus itself) sleeping in resume.

Regards
Martin

-----
diff -Nur v2.4.0-test12/drivers/pcmcia/pci_socket.c v2.4.0-t12-yenta1/driver/pcmcia/pci_socket.c
--- v2.4.0-test12/drivers/pcmcia/pci_socket.c	Wed Nov 29 21:47:10 2000
+++ v2.4.0-t12-yenta1/driver/pcmcia/pci_socket.c	Sun Dec 17 19:59:27 2000
@@ -178,6 +178,8 @@
 	socket->op = ops;
 	dev->driver_data = socket;
 	spin_lock_init(&socket->event_lock);
+	socket->pm_state = 0;
+	spin_lock_init(&socket->pm_lock);
 	return socket->op->open(socket);
 }
 
@@ -212,16 +214,83 @@
 	dev->driver_data = 0;
 }
 
+/* Delayed handler scheduled to complete the D3->D0 transition in the
+ * upper layers. We may sleep in pcmcia_resume_socket() with pm_lock
+ * hold - so we are save from resume re-entry due to other drivers
+ * sleeping in pci_pm resume handling.
+ */
+
+static void cardbus_resume_bh(void *data)
+{
+	pci_socket_t  *socket = (pci_socket_t *)data;
+
+	pcmcia_resume_socket(socket->pcmcia_socket);
+	socket->pm_state = 0;
+	spin_unlock(&socket->pm_lock);
+	MOD_DEC_USE_COUNT;
+}
+
+/* We are forced to implement asynch resume semantics because the
+ * pcmcia_resume path sleeps and we might get screwed by a second
+ * pci_pm_resume_device() hitting us in the middle of the first one.
+ * Which might happen anyway, if other drivers do not cooperate!
+ * So it's good to know we are protected by our socket->pm_lock.
+ */
+
+static void cardbus_change_pm_state(pci_socket_t *socket, int newstate)
+{
+	switch (newstate) {
+		case 3:
+			pcmcia_suspend_socket(socket->pcmcia_socket);
+			break;
+
+		case 0:
+			socket->tq_resume.routine = cardbus_resume_bh;
+			socket->tq_resume.data = socket;
+			MOD_INC_USE_COUNT;
+			schedule_task(&socket->tq_resume);
+			break;
+		default:
+			printk("cardbus: undefined power state\n");
+			break;
+	}
+}
+
+
 static void cardbus_suspend (struct pci_dev *dev)
 {
 	pci_socket_t *socket = (pci_socket_t *) dev->driver_data;
-	pcmcia_suspend_socket (socket->pcmcia_socket);
+
+	spin_lock(&socket->pm_lock);
+	if (socket->pm_state != 0) {
+		spin_unlock(&socket->pm_lock);
+		printk("cardbus: suspend of already suspended socket blocked\n");
+		return;
+	}
+	cardbus_change_pm_state(socket,3);
+	pci_set_power_state(dev,3);
+	socket->pm_state = 3;
+	spin_unlock(&socket->pm_lock);
 }
 
 static void cardbus_resume (struct pci_dev *dev)
 {
 	pci_socket_t *socket = (pci_socket_t *) dev->driver_data;
-	pcmcia_resume_socket (socket->pcmcia_socket);
+	
+	spin_lock(&socket->pm_lock);
+	if (socket->pm_state != 3) {
+		spin_unlock(&socket->pm_lock);
+		printk("cardbus: resume of non-suspended socket blocked\n");
+		return;
+	}
+	pci_set_power_state(dev,0);
+	cardbus_change_pm_state(socket, 0);
+
+	/* we intentionally leave with socket->pm_state not updated
+	 * and socket->pm_lock still acquired!
+	 * Will be released by the pending cardbus_resume_bh()
+	 * Needed to protect against resume re-entry.
+	 */
 }
 
 
diff -Nur v2.4.0-test12/drivers/pcmcia/pci_socket.h v2.4.0-t12-yenta1/driver/pcmcia/pci_socket.h
--- v2.4.0-test12/drivers/pcmcia/pci_socket.h	Wed Nov 29 21:47:10 2000
+++ v2.4.0-t12-yenta1/driver/pcmcia/pci_socket.h	Sun Dec 17 20:04:32 2000
@@ -26,6 +26,14 @@
 
 	/* A few words of private data for the low-level driver.. */
 	unsigned int private[8];
+
+	/* used for delayed resume completion handler */
+	struct tq_struct tq_resume;
+
+	/* to protect our pm state management */
+	unsigned int pm_state;
+	spinlock_t pm_lock;
+
 } pci_socket_t;
 
 struct pci_socket_ops {
diff -Nur v2.4.0-test12/drivers/pcmcia/yenta.c v2.4.0-t12-yenta1/driver/pcmcia/yenta.c
--- v2.4.0-test12/drivers/pcmcia/yenta.c	Wed Nov 29 21:47:10 2000
+++ v2.4.0-t12-yenta1/driver/pcmcia/yenta.c	Sun Dec 17 20:00:17 2000
@@ -629,8 +629,6 @@
 	u16 bridge;
 	struct pci_dev *dev = socket->dev;
 
-	pci_set_power_state(socket->dev, 0);
-
 	config_writel(socket, CB_LEGACY_MODE_BASE, 0);
 	config_writel(socket, PCI_BASE_ADDRESS_0, dev->resource[0].start);
 	config_writew(socket, PCI_COMMAND,
@@ -687,8 +685,6 @@
 	 * the IO and MEM bridging region data.. That is
 	 * something that pci_set_power_state() should
 	 * probably know about bridges anyway.
-	 *
-	pci_set_power_state(socket->dev, 3);
 	 */
 
 	return 0;


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/

  parent reply	other threads:[~2000-12-18 13:38 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <Pine.LNX.4.30.0012052110590.968-100000@localhost.localdomain>
2000-12-05 23:04 ` PCI irq routing Linus Torvalds
2000-12-05 23:25   ` Kai Germaschewski
2000-12-06  9:29   ` Martin Diehl
2000-12-06 17:49     ` Linus Torvalds
2000-12-07 18:30       ` Martin Diehl
2000-12-07 18:38         ` Linus Torvalds
2000-12-08  0:49           ` Martin Diehl
2000-12-11  1:46           ` [PATCH] VLSI irq router (was: PCI irq routing..) Martin Diehl
2000-12-15 18:39           ` yenta, pm, ioremap(!) problems " Martin Diehl
2000-12-15 18:55             ` Linus Torvalds
2000-12-16  0:21               ` Martin Diehl
2000-12-18 13:08               ` Martin Diehl [this message]
2000-12-18 13:10               ` [PATCH] yenta, pm - part 2 Martin Diehl

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Pine.LNX.4.21.0012181325370.579-100000@notebook.diehl.home \
    --to=mdiehlcs@compuserve.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mj@suse.cz \
    --cc=torvalds@transmeta.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).