Module Name: src Committed By: matt Date: Mon Jul 30 00:56:01 UTC 2012
Modified Files: src/sys/dev/sdmmc: sdhc.c Log Message: Make PIO on normal SDHC devices work correctly on big-endian machines. Add locking around interrupt manipulation (it should now be MP safe). To generate a diff of this commit: cvs rdiff -u -r1.28 -r1.29 src/sys/dev/sdmmc/sdhc.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/sdmmc/sdhc.c diff -u src/sys/dev/sdmmc/sdhc.c:1.28 src/sys/dev/sdmmc/sdhc.c:1.29 --- src/sys/dev/sdmmc/sdhc.c:1.28 Sat Jul 28 23:02:57 2012 +++ src/sys/dev/sdmmc/sdhc.c Mon Jul 30 00:56:01 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: sdhc.c,v 1.28 2012/07/28 23:02:57 matt Exp $ */ +/* $NetBSD: sdhc.c,v 1.29 2012/07/30 00:56:01 matt Exp $ */ /* $OpenBSD: sdhc.c,v 1.25 2009/01/13 19:44:20 grange Exp $ */ /* @@ -23,7 +23,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sdhc.c,v 1.28 2012/07/28 23:02:57 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sdhc.c,v 1.29 2012/07/30 00:56:01 matt Exp $"); #ifdef _KERNEL_OPT #include "opt_sdmmc.h" @@ -336,7 +336,7 @@ sdhc_host_found(struct sdhc_softc *sc, b * capabilities. (2.2.15) */ HWRITE1(hp, SDHC_TIMEOUT_CTL, SDHC_TIMEOUT_MAX); -#if 0 +#if 1 if (ISSET(hp->sc->sc_flags, SDHC_FLAG_ENHANCED)) HWRITE4(hp, SDHC_NINTR_STATUS, SDHC_CMD_TIMEOUT_ERROR << 16); #endif @@ -552,12 +552,13 @@ sdhc_host_reset1(sdmmc_chipset_handle_t /* Set data timeout counter value to max for now. */ HWRITE1(hp, SDHC_TIMEOUT_CTL, SDHC_TIMEOUT_MAX); -#if 0 +#if 1 if (ISSET(hp->sc->sc_flags, SDHC_FLAG_ENHANCED)) HWRITE4(hp, SDHC_NINTR_STATUS, SDHC_CMD_TIMEOUT_ERROR << 16); #endif /* Enable interrupts. */ + mutex_enter(&hp->intr_mtx); sdhcimask = SDHC_CARD_REMOVAL | SDHC_CARD_INSERTION | SDHC_BUFFER_READ_READY | SDHC_BUFFER_WRITE_READY | SDHC_DMA_INTERRUPT | SDHC_BLOCK_GAP_EVENT | @@ -576,6 +577,7 @@ sdhc_host_reset1(sdmmc_chipset_handle_t HWRITE2(hp, SDHC_NINTR_SIGNAL_EN, sdhcimask); HWRITE2(hp, SDHC_EINTR_SIGNAL_EN, SDHC_EINTR_SIGNAL_MASK); } + mutex_exit(&hp->intr_mtx); out: return error; @@ -936,7 +938,7 @@ sdhc_card_enable_intr(sdmmc_chipset_hand struct sdhc_host *hp = (struct sdhc_host *)sch; if (!ISSET(hp->sc->sc_flags, SDHC_FLAG_ENHANCED)) { - mutex_enter(&hp->host_mtx); + mutex_enter(&hp->intr_mtx); if (enable) { HSET2(hp, SDHC_NINTR_STATUS_EN, SDHC_CARD_INTERRUPT); HSET2(hp, SDHC_NINTR_SIGNAL_EN, SDHC_CARD_INTERRUPT); @@ -944,7 +946,7 @@ sdhc_card_enable_intr(sdmmc_chipset_hand HCLR2(hp, SDHC_NINTR_SIGNAL_EN, SDHC_CARD_INTERRUPT); HCLR2(hp, SDHC_NINTR_STATUS_EN, SDHC_CARD_INTERRUPT); } - mutex_exit(&hp->host_mtx); + mutex_exit(&hp->intr_mtx); } } @@ -954,9 +956,9 @@ sdhc_card_intr_ack(sdmmc_chipset_handle_ struct sdhc_host *hp = (struct sdhc_host *)sch; if (!ISSET(hp->sc->sc_flags, SDHC_FLAG_ENHANCED)) { - mutex_enter(&hp->host_mtx); + mutex_enter(&hp->intr_mtx); HSET2(hp, SDHC_NINTR_STATUS_EN, SDHC_CARD_INTERRUPT); - mutex_exit(&hp->host_mtx); + mutex_exit(&hp->intr_mtx); } } @@ -984,6 +986,7 @@ sdhc_exec_command(sdmmc_chipset_handle_t if (cmd->c_data && ISSET(hp->sc->sc_flags, SDHC_FLAG_ENHANCED)) { const uint16_t ready = SDHC_BUFFER_READ_READY | SDHC_BUFFER_WRITE_READY; + mutex_enter(&hp->intr_mtx); if (ISSET(hp->flags, SHF_USE_DMA)) { HCLR2(hp, SDHC_NINTR_SIGNAL_EN, ready); HCLR2(hp, SDHC_NINTR_STATUS_EN, ready); @@ -991,6 +994,7 @@ sdhc_exec_command(sdmmc_chipset_handle_t HSET2(hp, SDHC_NINTR_SIGNAL_EN, ready); HSET2(hp, SDHC_NINTR_STATUS_EN, ready); } + mutex_exit(&hp->intr_mtx); } /* @@ -1284,11 +1288,13 @@ sdhc_transfer_data_pio(struct sdhc_host while (datalen > 0) { if (!ISSET(HREAD4(hp, SDHC_PRESENT_STATE), imask)) { + mutex_enter(&hp->intr_mtx); if (ISSET(hp->sc->sc_flags, SDHC_FLAG_32BIT_ACCESS)) { HSET4(hp, SDHC_NINTR_SIGNAL_EN, imask); } else { HSET2(hp, SDHC_NINTR_SIGNAL_EN, imask); } + mutex_exit(&hp->intr_mtx); if (!sdhc_wait_intr(hp, imask, SDHC_BUFFER_TIMEOUT)) { error = ETIMEDOUT; break; @@ -1321,12 +1327,12 @@ sdhc_read_data_pio(struct sdhc_host *hp, if (((__uintptr_t)data & 3) == 0) { while (datalen > 3) { - *(uint32_t *)data = HREAD4(hp, SDHC_DATA); + *(uint32_t *)data = le32toh(HREAD4(hp, SDHC_DATA)); data += 4; datalen -= 4; } if (datalen > 1) { - *(uint16_t *)data = HREAD2(hp, SDHC_DATA); + *(uint16_t *)data = le16toh(HREAD2(hp, SDHC_DATA)); data += 2; datalen -= 2; } @@ -1337,7 +1343,7 @@ sdhc_read_data_pio(struct sdhc_host *hp, } } else if (((__uintptr_t)data & 1) == 0) { while (datalen > 1) { - *(uint16_t *)data = HREAD2(hp, SDHC_DATA); + *(uint16_t *)data = le16toh(HREAD2(hp, SDHC_DATA)); data += 2; datalen -= 2; } @@ -1361,12 +1367,12 @@ sdhc_write_data_pio(struct sdhc_host *hp if (((__uintptr_t)data & 3) == 0) { while (datalen > 3) { - HWRITE4(hp, SDHC_DATA, *(uint32_t *)data); + HWRITE4(hp, SDHC_DATA, htole32(*(uint32_t *)data)); data += 4; datalen -= 4; } if (datalen > 1) { - HWRITE2(hp, SDHC_DATA, *(uint16_t *)data); + HWRITE2(hp, SDHC_DATA, htole16(*(uint16_t *)data)); data += 2; datalen -= 2; } @@ -1377,7 +1383,7 @@ sdhc_write_data_pio(struct sdhc_host *hp } } else if (((__uintptr_t)data & 1) == 0) { while (datalen > 1) { - HWRITE2(hp, SDHC_DATA, *(uint16_t *)data); + HWRITE2(hp, SDHC_DATA, htole16(*(uint16_t *)data)); data += 2; datalen -= 2; } @@ -1578,6 +1584,8 @@ sdhc_intr(void *arg) DPRINTF(2,("%s: interrupt status=%x error=%x\n", HDEVNAME(hp), status, error)); + mutex_enter(&hp->intr_mtx); + /* Claim this interrupt. */ done = 1; @@ -1628,6 +1636,7 @@ sdhc_intr(void *arg) HCLR2(hp, SDHC_NINTR_STATUS_EN, SDHC_CARD_INTERRUPT); sdmmc_card_intr(hp->sdmmc); } + mutex_exit(&hp->intr_mtx); } return done;