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;

Reply via email to