svn commit: r291264 - head/sys/dev/usb/wlan

Andriy Voskoboinyk avos at FreeBSD.org
Tue Nov 24 19:20:47 UTC 2015


Author: avos
Date: Tue Nov 24 19:20:45 2015
New Revision: 291264
URL: https://svnweb.freebsd.org/changeset/base/291264

Log:
  urtwn(4): rework ROM reading.
  
  - Add error handling for urtwn_(r88e_)read_rom() and
  urtwn_efuse_*() functions.
  - Remove code duplication between urtwn_efuse_read() and
  urtwn_r88e_read_rom().
  - Merge r88e_rom and (r92c_)rom structures
  (only one of them can be used at the same time).
  - Other minor fixes / improvements.
  
  Tested with RTL8188EU, STA mode
  (URTWN_DEBUG + USB_DEBUG, hw.usb.urtwn.debug=3, no visual differences).
  
  Reviewed by:	kevlo
  Approved by:	adrian (mentor)
  Differential Revision:	https://reviews.freebsd.org/D4253

Modified:
  head/sys/dev/usb/wlan/if_urtwn.c
  head/sys/dev/usb/wlan/if_urtwnreg.h
  head/sys/dev/usb/wlan/if_urtwnvar.h

Modified: head/sys/dev/usb/wlan/if_urtwn.c
==============================================================================
--- head/sys/dev/usb/wlan/if_urtwn.c	Tue Nov 24 18:51:17 2015	(r291263)
+++ head/sys/dev/usb/wlan/if_urtwn.c	Tue Nov 24 19:20:45 2015	(r291264)
@@ -214,12 +214,19 @@ static void		urtwn_r88e_rf_write(struct 
 static uint32_t		urtwn_rf_read(struct urtwn_softc *, int, uint8_t);
 static int		urtwn_llt_write(struct urtwn_softc *, uint32_t,
 			    uint32_t);
-static uint8_t		urtwn_efuse_read_1(struct urtwn_softc *, uint16_t);
-static void		urtwn_efuse_read(struct urtwn_softc *);
+static int		urtwn_efuse_read_next(struct urtwn_softc *, uint8_t *);
+static int		urtwn_efuse_read_data(struct urtwn_softc *, uint8_t *,
+			    uint8_t, uint8_t);
+#ifdef URTWN_DEBUG
+static void		urtwn_dump_rom_contents(struct urtwn_softc *,
+			    uint8_t *, uint16_t);
+#endif
+static int		urtwn_efuse_read(struct urtwn_softc *, uint8_t *,
+			    uint16_t);
 static void		urtwn_efuse_switch_power(struct urtwn_softc *);
 static int		urtwn_read_chipid(struct urtwn_softc *);
-static void		urtwn_read_rom(struct urtwn_softc *);
-static void		urtwn_r88e_read_rom(struct urtwn_softc *);
+static int		urtwn_read_rom(struct urtwn_softc *);
+static int		urtwn_r88e_read_rom(struct urtwn_softc *);
 static int		urtwn_ra_init(struct urtwn_softc *);
 static void		urtwn_init_beacon(struct urtwn_softc *,
 			    struct urtwn_vap *);
@@ -431,9 +438,15 @@ urtwn_attach(device_t self)
 	}
 
 	if (sc->chip & URTWN_CHIP_88E)
-		urtwn_r88e_read_rom(sc);
+		error = urtwn_r88e_read_rom(sc);
 	else
-		urtwn_read_rom(sc);
+		error = urtwn_read_rom(sc);
+	if (error != 0) {
+		device_printf(sc->sc_dev, "%s: cannot read rom, error %d\n",
+		    __func__, error);
+		URTWN_UNLOCK(sc);
+		goto detach;
+	}
 
 	device_printf(sc->sc_dev, "MAC/BB RTL%s, RF 6052 %dT%dR\n",
 	    (sc->chip & URTWN_CHIP_92C) ? "8192CU" :
@@ -1224,68 +1237,137 @@ urtwn_llt_write(struct urtwn_softc *sc, 
 	return (ETIMEDOUT);
 }
 
-static uint8_t
-urtwn_efuse_read_1(struct urtwn_softc *sc, uint16_t addr)
+static int
+urtwn_efuse_read_next(struct urtwn_softc *sc, uint8_t *val)
 {
 	uint32_t reg;
 	int ntries;
 
+	if (sc->last_rom_addr >= URTWN_EFUSE_MAX_LEN)
+		return (EFAULT);
+
 	reg = urtwn_read_4(sc, R92C_EFUSE_CTRL);
-	reg = RW(reg, R92C_EFUSE_CTRL_ADDR, addr);
+	reg = RW(reg, R92C_EFUSE_CTRL_ADDR, sc->last_rom_addr);
 	reg &= ~R92C_EFUSE_CTRL_VALID;
+
 	urtwn_write_4(sc, R92C_EFUSE_CTRL, reg);
 	/* Wait for read operation to complete. */
 	for (ntries = 0; ntries < 100; ntries++) {
 		reg = urtwn_read_4(sc, R92C_EFUSE_CTRL);
 		if (reg & R92C_EFUSE_CTRL_VALID)
-			return (MS(reg, R92C_EFUSE_CTRL_DATA));
+			break;
 		urtwn_ms_delay(sc);
 	}
-	device_printf(sc->sc_dev,
-	    "could not read efuse byte at address 0x%x\n", addr);
-	return (0xff);
+	if (ntries == 100) {
+		device_printf(sc->sc_dev,
+		    "could not read efuse byte at address 0x%x\n",
+		    sc->last_rom_addr);
+		return (ETIMEDOUT);
+	}
+
+	*val = MS(reg, R92C_EFUSE_CTRL_DATA);
+	sc->last_rom_addr++;
+
+	return (0);
 }
 
+static int
+urtwn_efuse_read_data(struct urtwn_softc *sc, uint8_t *rom, uint8_t off,
+    uint8_t msk)
+{
+	uint8_t reg;
+	int i, error;
+
+	for (i = 0; i < 4; i++) {
+		if (msk & (1 << i))
+			continue;
+		error = urtwn_efuse_read_next(sc, &reg);
+		if (error != 0)
+			return (error);
+		DPRINTF("rom[0x%03X] == 0x%02X\n", off * 8 + i * 2, reg);
+		rom[off * 8 + i * 2 + 0] = reg;
+
+		error = urtwn_efuse_read_next(sc, &reg);
+		if (error != 0)
+			return (error);
+		DPRINTF("rom[0x%03X] == 0x%02X\n", off * 8 + i * 2 + 1, reg);
+		rom[off * 8 + i * 2 + 1] = reg;
+	}
+
+	return (0);
+}
+
+#ifdef URTWN_DEBUG
 static void
-urtwn_efuse_read(struct urtwn_softc *sc)
+urtwn_dump_rom_contents(struct urtwn_softc *sc, uint8_t *rom, uint16_t size)
 {
-	uint8_t *rom = (uint8_t *)&sc->rom;
-	uint16_t addr = 0;
-	uint32_t reg;
-	uint8_t off, msk;
 	int i;
 
+	/* Dump ROM contents. */
+	device_printf(sc->sc_dev, "%s:", __func__);
+	for (i = 0; i < size; i++) {
+		if (i % 32 == 0)
+			printf("\n%03X: ", i);
+		else if (i % 4 == 0)
+			printf(" ");
+
+		printf("%02X", rom[i]);
+	}
+	printf("\n");
+}
+#endif
+
+static int
+urtwn_efuse_read(struct urtwn_softc *sc, uint8_t *rom, uint16_t size)
+{
+#define URTWN_CHK(res) do {	\
+	if ((error = res) != 0)	\
+		goto end;	\
+} while(0)
+	uint8_t msk, off, reg;
+	int error;
+
 	urtwn_efuse_switch_power(sc);
 
-	memset(&sc->rom, 0xff, sizeof(sc->rom));
-	while (addr < 512) {
-		reg = urtwn_efuse_read_1(sc, addr);
-		if (reg == 0xff)
-			break;
-		addr++;
-		off = reg >> 4;
-		msk = reg & 0xf;
-		for (i = 0; i < 4; i++) {
-			if (msk & (1 << i))
+	/* Read full ROM image. */
+	sc->last_rom_addr = 0;
+	memset(rom, 0xff, size);
+
+	URTWN_CHK(urtwn_efuse_read_next(sc, &reg));
+	while (reg != 0xff) {
+		/* check for extended header */
+		if ((sc->chip & URTWN_CHIP_88E) && (reg & 0x1f) == 0x0f) {
+			off = reg >> 5;
+			URTWN_CHK(urtwn_efuse_read_next(sc, &reg));
+
+			if ((reg & 0x0f) != 0x0f)
+				off = ((reg & 0xf0) >> 1) | off;
+			else
 				continue;
-			rom[off * 8 + i * 2 + 0] =
-			    urtwn_efuse_read_1(sc, addr);
-			addr++;
-			rom[off * 8 + i * 2 + 1] =
-			    urtwn_efuse_read_1(sc, addr);
-			addr++;
-		}
+		} else
+			off = reg >> 4;
+		msk = reg & 0xf;
+
+		URTWN_CHK(urtwn_efuse_read_data(sc, rom, off, msk));
+		URTWN_CHK(urtwn_efuse_read_next(sc, &reg));
 	}
+
+end:
+
 #ifdef URTWN_DEBUG
-	if (urtwn_debug >= 2) {
-		/* Dump ROM content. */
-		printf("\n");
-		for (i = 0; i < sizeof(sc->rom); i++)
-			printf("%02x:", rom[i]);
-		printf("\n");
-	}
+	if (urtwn_debug >= 2)
+		urtwn_dump_rom_contents(sc, rom, size);
 #endif
+
 	urtwn_write_1(sc, R92C_EFUSE_ACCESS, R92C_EFUSE_ACCESS_OFF);
+
+	if (error != 0) {
+		device_printf(sc->sc_dev, "%s: error while reading ROM\n",
+		    __func__);
+	}
+
+	return (error);
+#undef URTWN_CHK
 }
 
 static void
@@ -1341,16 +1423,22 @@ urtwn_read_chipid(struct urtwn_softc *sc
 	return (0);
 }
 
-static void
+static int
 urtwn_read_rom(struct urtwn_softc *sc)
 {
-	struct r92c_rom *rom = &sc->rom;
+	struct r92c_rom *rom = &sc->rom.r92c_rom;
+	int error;
 
 	/* Read full ROM image. */
-	urtwn_efuse_read(sc);
+	error = urtwn_efuse_read(sc, (uint8_t *)rom, sizeof(*rom));
+	if (error != 0)
+		return (error);
 
 	/* XXX Weird but this is what the vendor driver does. */
-	sc->pa_setting = urtwn_efuse_read_1(sc, 0x1fa);
+	sc->last_rom_addr = 0x1fa;
+	error = urtwn_efuse_read_next(sc, &sc->pa_setting);
+	if (error != 0)
+		return (error);
 	DPRINTF("PA setting=0x%x\n", sc->pa_setting);
 
 	sc->board_type = MS(rom->rf_opt1, R92C_ROM_RF1_BOARD_TYPE);
@@ -1362,67 +1450,40 @@ urtwn_read_rom(struct urtwn_softc *sc)
 	sc->sc_rf_write = urtwn_r92c_rf_write;
 	sc->sc_power_on = urtwn_r92c_power_on;
 	sc->sc_dma_init = urtwn_r92c_dma_init;
+
+	return (0);
 }
 
-static void
+static int
 urtwn_r88e_read_rom(struct urtwn_softc *sc)
 {
-	uint8_t *rom = sc->r88e_rom;
-	uint16_t addr = 0;
-	uint32_t reg;
-	uint8_t off, msk, tmp;
-	int i;
-
-	off = 0;
-	urtwn_efuse_switch_power(sc);
-
-	/* Read full ROM image. */
-	memset(&sc->r88e_rom, 0xff, sizeof(sc->r88e_rom));
-	while (addr < 512) {
-		reg = urtwn_efuse_read_1(sc, addr);
-		if (reg == 0xff)
-			break;
-		addr++;
-		if ((reg & 0x1f) == 0x0f) {
-			tmp = (reg & 0xe0) >> 5;
-			reg = urtwn_efuse_read_1(sc, addr);
-			if ((reg & 0x0f) != 0x0f)
-				off = ((reg & 0xf0) >> 1) | tmp;
-			addr++;
-		} else
-			off = reg >> 4;
-		msk = reg & 0xf;
-		for (i = 0; i < 4; i++) {
-			if (msk & (1 << i))
-				continue;
-			rom[off * 8 + i * 2 + 0] =
-			    urtwn_efuse_read_1(sc, addr);
-			addr++;
-			rom[off * 8 + i * 2 + 1] =
-			    urtwn_efuse_read_1(sc, addr);
-			addr++;
-		}
-	}
+	uint8_t *rom = sc->rom.r88e_rom;
+	uint16_t addr;
+	int error, i;
 
-	urtwn_write_1(sc, R92C_EFUSE_ACCESS, R92C_EFUSE_ACCESS_OFF);
+	error = urtwn_efuse_read(sc, rom, sizeof(sc->rom.r88e_rom));
+	if (error != 0)
+		return (error);
 
 	addr = 0x10;
 	for (i = 0; i < 6; i++)
-		sc->cck_tx_pwr[i] = sc->r88e_rom[addr++];
+		sc->cck_tx_pwr[i] = rom[addr++];
 	for (i = 0; i < 5; i++)
-		sc->ht40_tx_pwr[i] = sc->r88e_rom[addr++];
-	sc->bw20_tx_pwr_diff = (sc->r88e_rom[addr] & 0xf0) >> 4;
+		sc->ht40_tx_pwr[i] = rom[addr++];
+	sc->bw20_tx_pwr_diff = (rom[addr] & 0xf0) >> 4;
 	if (sc->bw20_tx_pwr_diff & 0x08)
 		sc->bw20_tx_pwr_diff |= 0xf0;
-	sc->ofdm_tx_pwr_diff = (sc->r88e_rom[addr] & 0xf);
+	sc->ofdm_tx_pwr_diff = (rom[addr] & 0xf);
 	if (sc->ofdm_tx_pwr_diff & 0x08)
 		sc->ofdm_tx_pwr_diff |= 0xf0;
-	sc->regulatory = MS(sc->r88e_rom[0xc1], R92C_ROM_RF1_REGULATORY);
-	IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, &sc->r88e_rom[0xd7]);
+	sc->regulatory = MS(rom[0xc1], R92C_ROM_RF1_REGULATORY);
+	IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, &rom[0xd7]);
 
 	sc->sc_rf_write = urtwn_r88e_rf_write;
 	sc->sc_power_on = urtwn_r88e_power_on;
 	sc->sc_dma_init = urtwn_r88e_dma_init;
+
+	return (0);
 }
 
 /*
@@ -2944,7 +3005,7 @@ urtwn_bb_init(struct urtwn_softc *sc)
 		urtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), 0x69553420);
 		urtwn_ms_delay(sc);
 
-		crystalcap = sc->r88e_rom[0xb9];
+		crystalcap = sc->rom.r88e_rom[0xb9];
 		if (crystalcap == 0xff)
 			crystalcap = 0x20;
 		crystalcap &= 0x3f;
@@ -3210,7 +3271,7 @@ urtwn_get_txpower(struct urtwn_softc *sc
     uint16_t power[URTWN_RIDX_COUNT])
 {
 	struct ieee80211com *ic = &sc->sc_ic;
-	struct r92c_rom *rom = &sc->rom;
+	struct r92c_rom *rom = &sc->rom.r92c_rom;
 	uint16_t cckpow, ofdmpow, htpow, diff, max;
 	const struct urtwn_txpwr *base;
 	int ridx, chan, group;

Modified: head/sys/dev/usb/wlan/if_urtwnreg.h
==============================================================================
--- head/sys/dev/usb/wlan/if_urtwnreg.h	Tue Nov 24 18:51:17 2015	(r291263)
+++ head/sys/dev/usb/wlan/if_urtwnreg.h	Tue Nov 24 19:20:45 2015	(r291264)
@@ -938,6 +938,8 @@ struct r92c_rom {
 	uint8_t		curstomer_id;
 } __packed;
 
+#define	URTWN_EFUSE_MAX_LEN		512
+
 /* Rx MAC descriptor. */
 struct r92c_rx_stat {
 	uint32_t	rxdw0;

Modified: head/sys/dev/usb/wlan/if_urtwnvar.h
==============================================================================
--- head/sys/dev/usb/wlan/if_urtwnvar.h	Tue Nov 24 18:51:17 2015	(r291263)
+++ head/sys/dev/usb/wlan/if_urtwnvar.h	Tue Nov 24 19:20:45 2015	(r291264)
@@ -128,6 +128,11 @@ enum {
 
 #define	URTWN_EP_QUEUES	URTWN_BULK_RX
 
+union urtwn_rom {
+	struct r92c_rom			r92c_rom;
+	uint8_t				r88e_rom[URTWN_EFUSE_MAX_LEN];
+};
+
 struct urtwn_softc {
 	struct ieee80211com		sc_ic;
 	struct mbufq			sc_snd;
@@ -177,12 +182,12 @@ struct urtwn_softc {
 	struct urtwn_fw_info		fw;
 	void				*fw_virtaddr;
 
-	struct r92c_rom			rom;
-	uint8_t				r88e_rom[512];
+	union urtwn_rom			rom;
 	uint8_t				cck_tx_pwr[6];
 	uint8_t				ht40_tx_pwr[5];
 	int8_t				bw20_tx_pwr_diff;
 	int8_t				ofdm_tx_pwr_diff;
+	uint16_t			last_rom_addr;
 		
 	struct callout			sc_watchdog_ch;
 	struct mtx			sc_mtx;


More information about the svn-src-head mailing list