Hi, On Thu, Apr 21 2011, Takashi Iwai wrote: > On HP laptops with JMicron 388 chip, the write-locked SD card isn't > detected correctly as read-only in many cases. This is because the > PRESENT_STATE register becomes unsable just after plugging, and it > returns the WRITE_PROTECT bit wrongly at the first read. > > This patch fixes the read-only detection by adding a new sdhci quirk > indicating to check the register more intensively with a relatively > long delay. > > The patch is tested with 2.6.39-rc4 kernel. > > Cc: Aries Lee <arieslee@xxxxxxxxxxx> > Signed-off-by: Takashi Iwai <tiwai@xxxxxxx> > --- > v1->v2 > rewritten to use a quirk > > drivers/mmc/host/sdhci-pci.c | 5 +++++ > drivers/mmc/host/sdhci.c | 28 ++++++++++++++++++++++++---- > include/linux/mmc/sdhci.h | 2 ++ > 3 files changed, 31 insertions(+), 4 deletions(-) > > diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c > index a136be7..5781395 100644 > --- a/drivers/mmc/host/sdhci-pci.c > +++ b/drivers/mmc/host/sdhci-pci.c > @@ -329,6 +329,11 @@ static int jmicron_probe(struct sdhci_pci_chip *chip) > return ret; > } > > + /* quirk for unsable RO-detection on JM388 chips */ > + if (chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB388_SD || > + chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB388_ESD) > + chip->quirks |= SDHCI_QUIRK_UNSTABLE_RO_DETECT; > + > return 0; > } > > diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c > index 9e15f41..8097171 100644 > --- a/drivers/mmc/host/sdhci.c > +++ b/drivers/mmc/host/sdhci.c > @@ -1237,14 +1237,11 @@ out: > spin_unlock_irqrestore(&host->lock, flags); > } > > -static int sdhci_get_ro(struct mmc_host *mmc) > +static int check_ro(struct sdhci_host *host) > { > - struct sdhci_host *host; > unsigned long flags; > int is_readonly; > > - host = mmc_priv(mmc); > - > spin_lock_irqsave(&host->lock, flags); > > if (host->flags & SDHCI_DEVICE_DEAD) > @@ -1262,6 +1259,29 @@ static int sdhci_get_ro(struct mmc_host *mmc) > !is_readonly : is_readonly; > } > > +#define SAMPLE_COUNT 5 > + > +static int sdhci_get_ro(struct mmc_host *mmc) > +{ > + struct sdhci_host *host; > + int i, ro_count; > + > + host = mmc_priv(mmc); > + > + if (!(host->quirks & SDHCI_QUIRK_UNSTABLE_RO_DETECT)) > + return check_ro(host); > + > + ro_count = 0; > + for (i = 0; i < SAMPLE_COUNT; i++) { > + if (check_ro(host)) { > + if (++ro_count > SAMPLE_COUNT / 2) > + return 1; > + } > + msleep(30); > + } > + return 0; > +} > + > static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) > { > struct sdhci_host *host; > diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h > index 83bd9f7..92e1c9a 100644 > --- a/include/linux/mmc/sdhci.h > +++ b/include/linux/mmc/sdhci.h > @@ -85,6 +85,8 @@ struct sdhci_host { > #define SDHCI_QUIRK_NO_HISPD_BIT (1<<29) > /* Controller treats ADMA descriptors with length 0000h incorrectly */ > #define SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC (1<<30) > +/* The read-only detection via SDHCI_PRESENT_STATE register is unstable */ > +#define SDHCI_QUIRK_UNSTABLE_RO_DETECT (1<<31) > > int irq; /* Device IRQ */ > void __iomem *ioaddr; /* Mapped address */ Thanks, pushed to mmc-next for .39. - Chris. -- Chris Ball <cjb@xxxxxxxxxx> <http://printf.net/> One Laptop Per Child -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html