linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Felix Fietkau <nbd@openwrt.org>
To: linux-wireless <linux-wireless@vger.kernel.org>
Cc: Nick Kossifidis <mickflemm@gmail.com>, Bob Copeland <me@bobcopeland.com>
Subject: [PATCH,RFC 1/2] ath5k: extract more data from the eeprom for 2413 power calibration
Date: Fri, 30 Jan 2009 03:46:49 +0100	[thread overview]
Message-ID: <49826A19.9090005@openwrt.org> (raw)
In-Reply-To: <498269D5.7080204@openwrt.org>

Clean up the eeprom parsing code and prepare the pdgain
data for 2413, which will be required for power calibration code.
Also clean up some ugly line wrapping to make the code easier on
the eyes.

Signed-off-by: Felix Fietkau <nbd@openwrt.org>

--- a/drivers/net/wireless/ath5k/eeprom.c
+++ b/drivers/net/wireless/ath5k/eeprom.c
@@ -541,31 +541,30 @@ ath5k_eeprom_read_freq_list(struct ath5k
 {
 	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
 	int o = *offset;
-	int i = 0;
+	int i;
 	u8 freq1, freq2;
 	int ret;
 	u16 val;
 
+	ee->ee_n_piers[mode] = 0;
 	while(i < max) {
 		AR5K_EEPROM_READ(o++, val);
 
-		freq1 = (val >> 8) & 0xff;
-		freq2 = val & 0xff;
-
-		if (freq1) {
-			pc[i++].freq = ath5k_eeprom_bin2freq(ee,
-					freq1, mode);
-			ee->ee_n_piers[mode]++;
-		}
+		freq1 = val & 0xff;
+		if (!freq1)
+			break;
 
-		if (freq2) {
-			pc[i++].freq = ath5k_eeprom_bin2freq(ee,
-					freq2, mode);
-			ee->ee_n_piers[mode]++;
-		}
+		pc[i++].freq = ath5k_eeprom_bin2freq(ee,
+				freq1, mode);
+		ee->ee_n_piers[mode]++;
 
-		if (!freq1 || !freq2)
+		freq2 = (val >> 8) & 0xff;
+		if (!freq2)
 			break;
+
+		pc[i++].freq = ath5k_eeprom_bin2freq(ee,
+				freq2, mode);
+		ee->ee_n_piers[mode]++;
 	}
 
 	/* return new offset */
@@ -918,84 +917,46 @@ ath5k_cal_data_offset_2413(struct ath5k_
  * curves on eeprom. The final curve (higher power) has an extra
  * point for better accuracy like RF5112.
  */
+
 static int
-ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode)
+ath5k_eeprom_parse_pcal_info_2413(struct ath5k_hw *ah, int mode, u32 offset,
+                                  struct ath5k_chan_pcal_info *chinfo)
 {
 	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
-	struct ath5k_chan_pcal_info_rf2413 *chan_pcal_info;
-	struct ath5k_chan_pcal_info *gen_chan_info;
-	unsigned int i, c;
-	u32 offset;
+	struct ath5k_chan_pcal_info_rf2413 *pcinfo;
+	unsigned int i;
 	int ret;
 	u16 val;
-	u8 pd_gains = 0;
-
-	if (ee->ee_x_gain[mode] & 0x1) pd_gains++;
-	if ((ee->ee_x_gain[mode] >> 1) & 0x1) pd_gains++;
-	if ((ee->ee_x_gain[mode] >> 2) & 0x1) pd_gains++;
-	if ((ee->ee_x_gain[mode] >> 3) & 0x1) pd_gains++;
-	ee->ee_pd_gains[mode] = pd_gains;
+	u8 pd_gains;
 
-	offset = ath5k_cal_data_offset_2413(ee, mode);
-	ee->ee_n_piers[mode] = 0;
-	switch (mode) {
-	case AR5K_EEPROM_MODE_11A:
-		if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
-			return 0;
-
-		ath5k_eeprom_init_11a_pcal_freq(ah, offset);
-		offset += AR5K_EEPROM_N_5GHZ_CHAN / 2;
-		gen_chan_info = ee->ee_pwr_cal_a;
-		break;
-	case AR5K_EEPROM_MODE_11B:
-		if (!AR5K_EEPROM_HDR_11B(ee->ee_header))
-			return 0;
-
-		ath5k_eeprom_init_11bg_2413(ah, mode, offset);
-		offset += AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2;
-		gen_chan_info = ee->ee_pwr_cal_b;
-		break;
-	case AR5K_EEPROM_MODE_11G:
-		if (!AR5K_EEPROM_HDR_11G(ee->ee_header))
-			return 0;
-
-		ath5k_eeprom_init_11bg_2413(ah, mode, offset);
-		offset += AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2;
-		gen_chan_info = ee->ee_pwr_cal_g;
-		break;
-	default:
-		return -EINVAL;
-	}
+	pd_gains = ee->ee_pd_gains[mode];
 
 	if (pd_gains == 0)
 		return 0;
 
 	for (i = 0; i < ee->ee_n_piers[mode]; i++) {
-		chan_pcal_info = &gen_chan_info[i].rf2413_info;
+		pcinfo = &chinfo[i].rf2413_info;
 
 		/*
 		 * Read pwr_i, pddac_i and the first
 		 * 2 pd points (pwr, pddac)
 		 */
 		AR5K_EEPROM_READ(offset++, val);
-		chan_pcal_info->pwr_i[0] = val & 0x1f;
-		chan_pcal_info->pddac_i[0] = (val >> 5) & 0x7f;
-		chan_pcal_info->pwr[0][0] =
-					(val >> 12) & 0xf;
+		pcinfo->pwr_i[0] = val & 0x1f;
+		pcinfo->pddac_i[0] = (val >> 5) & 0x7f;
+		pcinfo->pwr[0][0] = (val >> 12) & 0xf;
 
 		AR5K_EEPROM_READ(offset++, val);
-		chan_pcal_info->pddac[0][0] = val & 0x3f;
-		chan_pcal_info->pwr[0][1] = (val >> 6) & 0xf;
-		chan_pcal_info->pddac[0][1] =
-					(val >> 10) & 0x3f;
+		pcinfo->pddac[0][0] = val & 0x3f;
+		pcinfo->pwr[0][1] = (val >> 6) & 0xf;
+		pcinfo->pddac[0][1] = (val >> 10) & 0x3f;
 
 		AR5K_EEPROM_READ(offset++, val);
-		chan_pcal_info->pwr[0][2] = val & 0xf;
-		chan_pcal_info->pddac[0][2] =
-					(val >> 4) & 0x3f;
+		pcinfo->pwr[0][2] = val & 0xf;
+		pcinfo->pddac[0][2] = (val >> 4) & 0x3f;
 
-		chan_pcal_info->pwr[0][3] = 0;
-		chan_pcal_info->pddac[0][3] = 0;
+		pcinfo->pwr[0][3] = 0;
+		pcinfo->pddac[0][3] = 0;
 
 		if (pd_gains > 1) {
 			/*
@@ -1003,44 +964,36 @@ ath5k_eeprom_read_pcal_info_2413(struct 
 			 * so it only has 2 pd points.
 			 * Continue wih pd gain 1.
 			 */
-			chan_pcal_info->pwr_i[1] = (val >> 10) & 0x1f;
+			pcinfo->pwr_i[1] = (val >> 10) & 0x1f;
 
-			chan_pcal_info->pddac_i[1] = (val >> 15) & 0x1;
+			pcinfo->pddac_i[1] = (val >> 15) & 0x1;
 			AR5K_EEPROM_READ(offset++, val);
-			chan_pcal_info->pddac_i[1] |= (val & 0x3F) << 1;
+			pcinfo->pddac_i[1] |= (val & 0x3F) << 1;
 
-			chan_pcal_info->pwr[1][0] = (val >> 6) & 0xf;
-			chan_pcal_info->pddac[1][0] =
-						(val >> 10) & 0x3f;
+			pcinfo->pwr[1][0] = (val >> 6) & 0xf;
+			pcinfo->pddac[1][0] = (val >> 10) & 0x3f;
 
 			AR5K_EEPROM_READ(offset++, val);
-			chan_pcal_info->pwr[1][1] = val & 0xf;
-			chan_pcal_info->pddac[1][1] =
-						(val >> 4) & 0x3f;
-			chan_pcal_info->pwr[1][2] =
-						(val >> 10) & 0xf;
+			pcinfo->pwr[1][1] = val & 0xf;
+			pcinfo->pddac[1][1] = (val >> 4) & 0x3f;
+			pcinfo->pwr[1][2] = (val >> 10) & 0xf;
 
-			chan_pcal_info->pddac[1][2] =
-						(val >> 14) & 0x3;
+			pcinfo->pddac[1][2] = (val >> 14) & 0x3;
 			AR5K_EEPROM_READ(offset++, val);
-			chan_pcal_info->pddac[1][2] |=
-						(val & 0xF) << 2;
+			pcinfo->pddac[1][2] |= (val & 0xF) << 2;
 
-			chan_pcal_info->pwr[1][3] = 0;
-			chan_pcal_info->pddac[1][3] = 0;
+			pcinfo->pwr[1][3] = 0;
+			pcinfo->pddac[1][3] = 0;
 		} else if (pd_gains == 1) {
 			/*
 			 * Pd gain 0 is the last one so
 			 * read the extra point.
 			 */
-			chan_pcal_info->pwr[0][3] =
-						(val >> 10) & 0xf;
+			pcinfo->pwr[0][3] = (val >> 10) & 0xf;
 
-			chan_pcal_info->pddac[0][3] =
-						(val >> 14) & 0x3;
+			pcinfo->pddac[0][3] = (val >> 14) & 0x3;
 			AR5K_EEPROM_READ(offset++, val);
-			chan_pcal_info->pddac[0][3] |=
-						(val & 0xF) << 2;
+			pcinfo->pddac[0][3] |= (val & 0xF) << 2;
 		}
 
 		/*
@@ -1048,105 +1001,159 @@ ath5k_eeprom_read_pcal_info_2413(struct 
 		 * as above.
 		 */
 		if (pd_gains > 2) {
-			chan_pcal_info->pwr_i[2] = (val >> 4) & 0x1f;
-			chan_pcal_info->pddac_i[2] = (val >> 9) & 0x7f;
+			pcinfo->pwr_i[2] = (val >> 4) & 0x1f;
+			pcinfo->pddac_i[2] = (val >> 9) & 0x7f;
 
 			AR5K_EEPROM_READ(offset++, val);
-			chan_pcal_info->pwr[2][0] =
-						(val >> 0) & 0xf;
-			chan_pcal_info->pddac[2][0] =
-						(val >> 4) & 0x3f;
-			chan_pcal_info->pwr[2][1] =
-						(val >> 10) & 0xf;
-
-			chan_pcal_info->pddac[2][1] =
-						(val >> 14) & 0x3;
-			AR5K_EEPROM_READ(offset++, val);
-			chan_pcal_info->pddac[2][1] |=
-						(val & 0xF) << 2;
-
-			chan_pcal_info->pwr[2][2] =
-						(val >> 4) & 0xf;
-			chan_pcal_info->pddac[2][2] =
-						(val >> 8) & 0x3f;
+			pcinfo->pwr[2][0] = (val >> 0) & 0xf;
+			pcinfo->pddac[2][0] = (val >> 4) & 0x3f;
+			pcinfo->pwr[2][1] = (val >> 10) & 0xf;
 
-			chan_pcal_info->pwr[2][3] = 0;
-			chan_pcal_info->pddac[2][3] = 0;
+			pcinfo->pddac[2][1] = (val >> 14) & 0x3;
+			AR5K_EEPROM_READ(offset++, val);
+			pcinfo->pddac[2][1] |= (val & 0xF) << 2;
+
+			pcinfo->pwr[2][2] = (val >> 4) & 0xf;
+			pcinfo->pddac[2][2] = (val >> 8) & 0x3f;
+
+			pcinfo->pwr[2][3] = 0;
+			pcinfo->pddac[2][3] = 0;
 		} else if (pd_gains == 2) {
-			chan_pcal_info->pwr[1][3] =
-						(val >> 4) & 0xf;
-			chan_pcal_info->pddac[1][3] =
-						(val >> 8) & 0x3f;
+			pcinfo->pwr[1][3] = (val >> 4) & 0xf;
+			pcinfo->pddac[1][3] = (val >> 8) & 0x3f;
 		}
 
 		if (pd_gains > 3) {
-			chan_pcal_info->pwr_i[3] = (val >> 14) & 0x3;
+			pcinfo->pwr_i[3] = (val >> 14) & 0x3;
 			AR5K_EEPROM_READ(offset++, val);
-			chan_pcal_info->pwr_i[3] |= ((val >> 0) & 0x7) << 2;
+			pcinfo->pwr_i[3] |= ((val >> 0) & 0x7) << 2;
 
-			chan_pcal_info->pddac_i[3] = (val >> 3) & 0x7f;
-			chan_pcal_info->pwr[3][0] =
-						(val >> 10) & 0xf;
-			chan_pcal_info->pddac[3][0] =
-						(val >> 14) & 0x3;
+			pcinfo->pddac_i[3] = (val >> 3) & 0x7f;
+			pcinfo->pwr[3][0] = (val >> 10) & 0xf;
+			pcinfo->pddac[3][0] = (val >> 14) & 0x3;
 
 			AR5K_EEPROM_READ(offset++, val);
-			chan_pcal_info->pddac[3][0] |=
-						(val & 0xF) << 2;
-			chan_pcal_info->pwr[3][1] =
-						(val >> 4) & 0xf;
-			chan_pcal_info->pddac[3][1] =
-						(val >> 8) & 0x3f;
+			pcinfo->pddac[3][0] |= (val & 0xF) << 2;
+			pcinfo->pwr[3][1] = (val >> 4) & 0xf;
+			pcinfo->pddac[3][1] = (val >> 8) & 0x3f;
 
-			chan_pcal_info->pwr[3][2] =
-						(val >> 14) & 0x3;
+			pcinfo->pwr[3][2] = (val >> 14) & 0x3;
 			AR5K_EEPROM_READ(offset++, val);
-			chan_pcal_info->pwr[3][2] |=
-						((val >> 0) & 0x3) << 2;
+			pcinfo->pwr[3][2] |= ((val >> 0) & 0x3) << 2;
 
-			chan_pcal_info->pddac[3][2] =
-						(val >> 2) & 0x3f;
-			chan_pcal_info->pwr[3][3] =
-						(val >> 8) & 0xf;
+			pcinfo->pddac[3][2] = (val >> 2) & 0x3f;
+			pcinfo->pwr[3][3] = (val >> 8) & 0xf;
 
-			chan_pcal_info->pddac[3][3] =
-						(val >> 12) & 0xF;
+			pcinfo->pddac[3][3] = (val >> 12) & 0xF;
 			AR5K_EEPROM_READ(offset++, val);
-			chan_pcal_info->pddac[3][3] |=
-						((val >> 0) & 0x3) << 4;
+			pcinfo->pddac[3][3] |= ((val >> 0) & 0x3) << 4;
 		} else if (pd_gains == 3) {
-			chan_pcal_info->pwr[2][3] =
-						(val >> 14) & 0x3;
+			pcinfo->pwr[2][3] = (val >> 14) & 0x3;
 			AR5K_EEPROM_READ(offset++, val);
-			chan_pcal_info->pwr[2][3] |=
-						((val >> 0) & 0x3) << 2;
+			pcinfo->pwr[2][3] |= ((val >> 0) & 0x3) << 2;
 
-			chan_pcal_info->pddac[2][3] =
-						(val >> 2) & 0x3f;
+			pcinfo->pddac[2][3] = (val >> 2) & 0x3f;
 		}
+	}
+	return 0;
+}
+
+static int
+ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode,
+                                    struct ath5k_chan_pcal_info *chinfo,
+                                    unsigned int *xgains)
+{
+	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+	struct ath5k_chan_pcal_info_rf2413 *pcinfo;
+	unsigned int i, j, k;
 
-		for (c = 0; c < pd_gains; c++) {
-			/* Recreate pwr table for this channel using pwr steps */
-			chan_pcal_info->pwr[c][0] += chan_pcal_info->pwr_i[c] * 2;
-			chan_pcal_info->pwr[c][1] += chan_pcal_info->pwr[c][0];
-			chan_pcal_info->pwr[c][2] += chan_pcal_info->pwr[c][1];
-			chan_pcal_info->pwr[c][3] += chan_pcal_info->pwr[c][2];
-			if (chan_pcal_info->pwr[c][3] == chan_pcal_info->pwr[c][2])
-				chan_pcal_info->pwr[c][3] = 0;
-
-			/* Recreate pddac table for this channel using pddac steps */
-			chan_pcal_info->pddac[c][0] += chan_pcal_info->pddac_i[c];
-			chan_pcal_info->pddac[c][1] += chan_pcal_info->pddac[c][0];
-			chan_pcal_info->pddac[c][2] += chan_pcal_info->pddac[c][1];
-			chan_pcal_info->pddac[c][3] += chan_pcal_info->pddac[c][2];
-			if (chan_pcal_info->pddac[c][3] == chan_pcal_info->pddac[c][2])
-				chan_pcal_info->pddac[c][3] = 0;
+	/* prepare the raw values */
+	for (i = 0; i < ee->ee_n_piers[mode]; i++) {
+		pcinfo = &chinfo[i].rf2413_info;
+		for (j = 0; j < ee->ee_pd_gains[mode]; j++) {
+			unsigned int idx = xgains[j];
+			struct ath5k_pdgain_info *pd = &pcinfo->pdgains[idx];
+
+			/* one more point for the highest power (lowest gain) */
+			if (j == ee->ee_pd_gains[mode] - 1) {
+				pd->n_vpd = AR5K_EEPROM_N_PD_POINTS;
+			} else {
+				pd->n_vpd = AR5K_EEPROM_N_PD_POINTS - 1;
+			}
+
+			pd->vpd[0] = pcinfo->pddac_i[j];
+			pd->pwr_t4[0] = 4 * pcinfo->pwr_i[j];
+			for (k = 1; k < pd->n_vpd; k++) {
+				pd->pwr_t4[k] = pd->pwr_t4[k - 1] + 2 * pcinfo->pwr[j][k - 1];
+				pd->vpd[k] = pd->vpd[k - 1] + pcinfo->pddac[j][k - 1];
+			}
 		}
 	}
 
 	return 0;
 }
 
+static int
+ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode)
+{
+	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+	struct ath5k_chan_pcal_info *chinfo;
+	unsigned int xgains[AR5K_EEPROM_N_PD_GAINS];
+	u32 offset;
+	u8 pd_gains = 0;
+	int i, ret;
+
+	memset(xgains, 0, sizeof(xgains));
+	for (i = 0; i < AR5K_EEPROM_N_PD_GAINS; i++) {
+		int idx = AR5K_EEPROM_N_PD_GAINS - i - 1;
+
+		if ((ee->ee_x_gain[mode] >> idx) & 0x1)
+			xgains[pd_gains++] = idx;
+	}
+	ee->ee_pd_gains[mode] = pd_gains;
+
+	offset = ath5k_cal_data_offset_2413(ee, mode);
+	switch (mode) {
+	case AR5K_EEPROM_MODE_11A:
+		if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
+			return 0;
+
+		ath5k_eeprom_init_11a_pcal_freq(ah, offset);
+		offset += AR5K_EEPROM_N_5GHZ_CHAN / 2;
+		chinfo = ee->ee_pwr_cal_a;
+		break;
+	case AR5K_EEPROM_MODE_11B:
+		if (!AR5K_EEPROM_HDR_11B(ee->ee_header))
+			return 0;
+
+		ath5k_eeprom_init_11bg_2413(ah, mode, offset);
+		offset += AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2;
+		chinfo = ee->ee_pwr_cal_b;
+		break;
+	case AR5K_EEPROM_MODE_11G:
+		if (!AR5K_EEPROM_HDR_11G(ee->ee_header))
+			return 0;
+
+		ath5k_eeprom_init_11bg_2413(ah, mode, offset);
+		offset += AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2;
+		chinfo = ee->ee_pwr_cal_g;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+
+	ret = ath5k_eeprom_parse_pcal_info_2413(ah, mode, offset, chinfo);
+	if (ret)
+		return ret;
+
+	ret = ath5k_eeprom_convert_pcal_info_2413(ah, mode, chinfo, xgains);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
 /*
  * Read per rate target power (this is the maximum tx power
  * supported by the card). This info is used when setting
@@ -1264,6 +1271,7 @@ ath5k_eeprom_read_pcal_info(struct ath5k
 	else
 		read_pcal = ath5k_eeprom_read_pcal_info_5111;
 
+
 	for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++) {
 		err = read_pcal(ah, mode);
 		if (err)
--- a/drivers/net/wireless/ath5k/eeprom.h
+++ b/drivers/net/wireless/ath5k/eeprom.h
@@ -265,15 +265,27 @@ struct ath5k_chan_pcal_info_rf5112 {
 	u8	pcdac_x3[AR5K_EEPROM_N_XPD3_POINTS];
 };
 
+
+struct ath5k_pdgain_info {
+	u16 n_vpd;
+	u16 vpd[AR5K_EEPROM_N_PD_POINTS];
+	s16 pwr_t4[AR5K_EEPROM_N_PD_POINTS];
+};
+
 struct ath5k_chan_pcal_info_rf2413 {
+	/* --- EEPROM VALUES --- */
 	/* Starting pwr/pddac values */
-	s8		pwr_i[AR5K_EEPROM_N_PD_GAINS];
-	u8	pddac_i[AR5K_EEPROM_N_PD_GAINS];
+	s8 pwr_i[AR5K_EEPROM_N_PD_GAINS];
+	u8 pddac_i[AR5K_EEPROM_N_PD_GAINS];
 	/* (pwr,pddac) points */
-	s8		pwr[AR5K_EEPROM_N_PD_GAINS]
-				[AR5K_EEPROM_N_PD_POINTS];
-	u8	pddac[AR5K_EEPROM_N_PD_GAINS]
-				[AR5K_EEPROM_N_PD_POINTS];
+	s8 pwr[AR5K_EEPROM_N_PD_GAINS]
+	      [AR5K_EEPROM_N_PD_POINTS];
+	u8 pddac[AR5K_EEPROM_N_PD_GAINS]
+	        [AR5K_EEPROM_N_PD_POINTS];
+
+	/* --- RAW VALUES --- */
+	struct ath5k_pdgain_info pdgains
+		[AR5K_EEPROM_N_PD_GAINS];
 };
 
 struct ath5k_chan_pcal_info {


  reply	other threads:[~2009-01-30  2:46 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-01-30  2:45 [PATCH,RFC 0/2] ath5k: implement tx power calibration on ar2413/5413 Felix Fietkau
2009-01-30  2:46 ` Felix Fietkau [this message]
2009-01-30  2:48 ` [PATCH,RFC 2/2] " Felix Fietkau
2009-01-30  8:17 ` [PATCH,RFC 0/2] " Nick Kossifidis
2009-01-30 14:47   ` Bob Copeland
2009-01-30 15:08     ` Nick Kossifidis
2009-01-30 13:39 ` Bob Copeland

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=49826A19.9090005@openwrt.org \
    --to=nbd@openwrt.org \
    --cc=linux-wireless@vger.kernel.org \
    --cc=me@bobcopeland.com \
    --cc=mickflemm@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).