From rmk@arm.linux.org.uk Thu Sep  8 22:51:56 2005
Return-Path: <rmk+rpurdie=rpsys.net@arm.linux.org.uk>
Received: from localhost (localhost [127.0.0.1]) by tim.rpsys.net
	(8.13.1/8.12.10) with ESMTP id j88LpuRW001179 for <rpurdie@rpsys.net>; Thu,
	8 Sep 2005 22:51:56 +0100
Received: from tim.rpsys.net ([127.0.0.1]) by localhost (tim [127.0.0.1])
	(amavisd-new, port 10024) with LMTP id 00797-10 for <rpurdie@rpsys.net>;
	Thu,  8 Sep 2005 22:51:56 +0100 (BST)
Received: from caramon.arm.linux.org.uk (caramon.arm.linux.org.uk
	[212.18.232.186]) by tim.rpsys.net (8.13.1/8.12.10) with ESMTP id
	j88Lpnoj001167 (version=TLSv1/SSLv3 cipher=EDH-RSA-DES-CBC3-SHA bits=168
	verify=NO) for <rpurdie@rpsys.net>; Thu, 8 Sep 2005 22:51:50 +0100
Received: from flint.arm.linux.org.uk
	([2002:d412:e8ba:1:201:2ff:fe14:8fad]) by caramon.arm.linux.org.uk with
	asmtp (TLSv1:DES-CBC3-SHA:168) (Exim 4.41) id 1EDUJ9-0003UX-58 for
	rpurdie@rpsys.net; Thu, 08 Sep 2005 22:51:47 +0100
Received: from rmk by flint.arm.linux.org.uk with local (Exim 4.41) id
	1EDUJ7-0006Pf-Rf for rpurdie@rpsys.net; Thu, 08 Sep 2005 22:51:45 +0100
Date: Thu, 8 Sep 2005 22:51:45 +0100
From: Russell King <rmk@arm.linux.org.uk>
To: Richard Purdie <rpurdie@rpsys.net>
Subject: Re: [-mm patch 5/5] SharpSL: Add new ARM PXA machines Spitz and
	Borzoi with partial Akita Support
Message-ID: <20050908225145.A24504@flint.arm.linux.org.uk>
References: <1126007632.8338.130.camel@localhost.localdomain>
	 <20050908132340.D31595@flint.arm.linux.org.uk>
	 <1126191158.8147.61.camel@localhost.localdomain>
	 <20050908155926.B5661@flint.arm.linux.org.uk>
	 <1126194477.8147.120.camel@localhost.localdomain>
	 <20050908174755.H5661@flint.arm.linux.org.uk>
	 <1126207899.8147.156.camel@localhost.localdomain>
	 <20050908203814.M5661@flint.arm.linux.org.uk>
	 <1126212604.8147.167.camel@localhost.localdomain>
	 <20050908215218.C19542@flint.arm.linux.org.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
User-Agent: Mutt/1.2.5.1i
In-Reply-To: <20050908215218.C19542@flint.arm.linux.org.uk>; from rmk@arm.linux.org.uk on Thu, Sep 08, 2005 at 09:52:18PM +0100
Sender: Russell King <rmk@arm.linux.org.uk>
X-Spam-Checker-Version: SpamAssassin 3.0.4 (2005-06-05) on tim.rpsys.net
X-Spam-Level: 
X-Spam-Status: No, score=-2.6 required=5.0 tests=AWL,BAYES_00 autolearn=ham
	 version=3.0.4
X-Evolution-Source: imap://richard@tim.rpsys.net/
Content-Transfer-Encoding: 8bit

On Thu, Sep 08, 2005 at 09:52:18PM +0100, Russell King wrote:
> On Thu, Sep 08, 2005 at 09:50:04PM +0100, Richard Purdie wrote:
> > On Thu, 2005-09-08 at 20:38 +0100, Russell King wrote:
> > > On Thu, Sep 08, 2005 at 08:31:39PM +0100, Richard Purdie wrote:
> > > > The problem was that the mmc_priv define isn't very careful about its
> > > > casting. If you called mmc_priv with a void pointer, nasty things
> > > > happen.
> > > > 
> > > > The revised section of the patch below gives one fix to the problem. The
> > > > alternative to this is to add an intermediate state in
> > > > pxamci_detect_irq() of:
> > > > 
> > > > struct mmc_host *mmc = devid;
> > > > struct pxamci_host *host = mmc_priv(mmc);
> > > 
> > > Or we change mmc_host to be:
> > > 
> > > struct mmc_host {
> > > 	...
> > >         struct work_struct      detect;
> > > 	unsigned long		private[0] ____cacheline_aligned;
> > > };
> > > 
> > > and change mmc_priv() to be:
> > > 
> > > #define mmc_priv(x)	((void *)((struct mmc_host *)(x))->private)
> > > 
> > > which should be more portable.
> > 
> > This is also fine :) (I've also quickly tested it). How do you want me
> > to go about submitting the changes? (or are you going to handle it?)
> 
> I've already thrown the first patch in.  I'll put the above in next,
> followed by the PXA change.  I think that's about as much as can
> happen against -linus.
> 
> akpm will pick up those changes tonight, so you shouldn't need to
> worry about them (except letting akpm know that they depend on the
> git-mmc tree.)

Right, here's the combined diff from git-mmc.  I made one additional
change - the mmc_priv now has typechecking as well.

This is the first two patches I recently sent, plus the mmc_priv fix.

From: Richard Purdie: Thu Sep  8 22:48:16 BST 2005

        [MMC] Add mmc_detect_change() delay support for PXAMCI driver

        Allow PXA platforms to pass an appropriate delay value to the
        PXA MCI driver for delaying detection changes.

        Signed-Off-By: Richard Purdie <rpurdie@rpsys.net>
        Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

From: Russell King: Thu Sep  8 22:46:00 BST 2005

        [MMC] Ensure correct mmc_priv() behaviour

        mmc_priv() has some nasty effects if the wrong pointer type is
        passed to it.  Introduce type checking, which also means we get
        the right type.  Also add an additional member to mmc_host which
        is used to align host-private data appropriately.

        Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

From: Richard Purdie: Thu Sep  8 17:53:01 BST 2005

        [MMC] Allow detection/removal to be delayed

        Change mmc_detect_change() to take a delay argument such that
        the detection of card insertions and removals can be delayed
        according to the requirements of the host driver or platform.

        Signed-off-by: Richard Purdie <rpurdie@rpsys.net>
        Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1079,13 +1079,17 @@ static void mmc_setup(struct mmc_host *h
 /**
  *	mmc_detect_change - process change of state on a MMC socket
  *	@host: host which changed state.
+ *	@delay: optional delay to wait before detection (jiffies)
  *
  *	All we know is that card(s) have been inserted or removed
  *	from the socket(s).  We don't know which socket or cards.
  */
-void mmc_detect_change(struct mmc_host *host)
+void mmc_detect_change(struct mmc_host *host, unsigned long delay)
 {
-	schedule_work(&host->detect);
+	if (delay)
+		schedule_delayed_work(&host->detect, delay);
+	else
+		schedule_work(&host->detect);
 }
 
 EXPORT_SYMBOL(mmc_detect_change);
@@ -1189,7 +1193,7 @@ int mmc_add_host(struct mmc_host *host)
 	ret = mmc_add_host_sysfs(host);
 	if (ret == 0) {
 		mmc_power_off(host);
-		mmc_detect_change(host);
+		mmc_detect_change(host, 0);
 	}
 
 	return ret;
@@ -1259,7 +1263,7 @@ EXPORT_SYMBOL(mmc_suspend_host);
  */
 int mmc_resume_host(struct mmc_host *host)
 {
-	mmc_detect_change(host);
+	mmc_detect_change(host, 0);
 
 	return 0;
 }
diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c
--- a/drivers/mmc/mmci.c
+++ b/drivers/mmc/mmci.c
@@ -442,7 +442,7 @@ static void mmci_check_status(unsigned l
 
 	status = host->plat->status(mmc_dev(host->mmc));
 	if (status ^ host->oldstat)
-		mmc_detect_change(host->mmc);
+		mmc_detect_change(host->mmc, 0);
 
 	host->oldstat = status;
 	mod_timer(&host->timer, jiffies + HZ);
diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c
--- a/drivers/mmc/pxamci.c
+++ b/drivers/mmc/pxamci.c
@@ -423,7 +423,9 @@ static void pxamci_dma_irq(int dma, void
 
 static irqreturn_t pxamci_detect_irq(int irq, void *devid, struct pt_regs *regs)
 {
-	mmc_detect_change(devid);
+	struct pxamci_host *host = mmc_priv(devid);
+
+	mmc_detect_change(devid, host->pdata->detect_delay);
 	return IRQ_HANDLED;
 }
 
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c
--- a/drivers/mmc/wbsd.c
+++ b/drivers/mmc/wbsd.c
@@ -1122,7 +1122,7 @@ static void wbsd_detect_card(unsigned lo
 	
 	DBG("Executing card detection\n");
 	
-	mmc_detect_change(host->mmc);	
+	mmc_detect_change(host->mmc, 0);	
 }
 
 /*
@@ -1198,7 +1198,7 @@ static void wbsd_tasklet_card(unsigned l
 		 */
 		spin_unlock(&host->lock);
 
-		mmc_detect_change(host->mmc);
+		mmc_detect_change(host->mmc, 0);
 	}
 	else
 		spin_unlock(&host->lock);
diff --git a/include/asm-arm/arch-pxa/mmc.h b/include/asm-arm/arch-pxa/mmc.h
--- a/include/asm-arm/arch-pxa/mmc.h
+++ b/include/asm-arm/arch-pxa/mmc.h
@@ -9,6 +9,7 @@ struct mmc_host;
 
 struct pxamci_platform_data {
 	unsigned int ocr_mask;			/* available voltages */
+	unsigned long detect_delay;		/* delay in jiffies before detecting cards after interrupt */
 	int (*init)(struct device *, irqreturn_t (*)(int, void *, struct pt_regs *), void *);
 	int (*get_ro)(struct device *);
 	void (*setpower)(struct device *, unsigned int);
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -109,6 +109,8 @@ struct mmc_host {
 	struct mmc_card		*card_selected;	/* the selected MMC card */
 
 	struct work_struct	detect;
+
+	unsigned long		private[0] ____cacheline_aligned;
 };
 
 extern struct mmc_host *mmc_alloc_host(int extra, struct device *);
@@ -116,14 +118,18 @@ extern int mmc_add_host(struct mmc_host 
 extern void mmc_remove_host(struct mmc_host *);
 extern void mmc_free_host(struct mmc_host *);
 
-#define mmc_priv(x)	((void *)((x) + 1))
+static inline void *mmc_priv(struct mmc_host *host)
+{
+	return (void *)host->private;
+}
+
 #define mmc_dev(x)	((x)->dev)
 #define mmc_hostname(x)	((x)->class_dev.class_id)
 
 extern int mmc_suspend_host(struct mmc_host *, pm_message_t);
 extern int mmc_resume_host(struct mmc_host *);
 
-extern void mmc_detect_change(struct mmc_host *);
+extern void mmc_detect_change(struct mmc_host *, unsigned long delay);
 extern void mmc_request_done(struct mmc_host *, struct mmc_request *);
 
 #endif


-- 
Russell King


