* Add debug code for displaying EEPROM data. Tested on various chip combinations, on x86 and IXP43x (armv5te). It has many > 80cols warnings but i
don't think it'll be more readable if i start breaking lines, it's already messy, after all it's debug code. This code also replaces ath_info tool.
Signed-Off-by: Nick Kossifidis <[email protected]>
---
diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath5k/debug.c
index ccaeb5c..f0ef5b3 100644
--- a/drivers/net/wireless/ath5k/debug.c
+++ b/drivers/net/wireless/ath5k/debug.c
@@ -324,6 +324,858 @@ static const struct file_operations fops_reset = {
.owner = THIS_MODULE,
};
+/* debugfs: EEPROM stuff */
+
+/* EEPROM Header (common) */
+static ssize_t read_file_eeprom_header(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+
+ struct ath5k_softc *sc = file->private_data;
+ struct ath5k_hw *ah = sc->ah;
+ struct ath5k_eeprom_info ee = ah->ah_capabilities.cap_eeprom;
+ char buf[2000];
+ unsigned int len = 0;
+ u16 eeprom_size;
+ u8 eesize;
+
+ eesize = AR5K_REG_MS(ath5k_hw_reg_read(ah, AR5K_PCICFG),
+ AR5K_PCICFG_EESIZE);
+
+ if (eesize == 0)
+ eeprom_size = 4096 / 8;
+ else if (eesize == 1)
+ eeprom_size = 8192 / 8;
+ else if (eesize == 2)
+ eeprom_size = 16384 / 8;
+ else
+ eeprom_size = 0;
+
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "/==============[EEPROM Information]=============\\\n");
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| EEPROM Version: %1x.%1x |",
+ (ee.ee_version & 0xF000) >> 12, ee.ee_version & 0xFFF);
+ len += snprintf(buf+len, sizeof(buf)-len,
+ " EEPROM Size: %3d kbit |\n", eeprom_size * 8 / 1024);
+
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| EEMAP: %i |", AR5K_EEPROM_EEMAP(ee.ee_misc0));
+
+ len += snprintf(buf+len, sizeof(buf)-len,
+ " Reg. Domain: 0x%02X |\n", ee.ee_regdomain);
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "\\===============================================/\n\n");
+
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "/==================[Capabilities]================\\\n");
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| 802.11a Support: ");
+ if (AR5K_EEPROM_HDR_11A(ee.ee_header))
+ len += snprintf(buf+len, sizeof(buf)-len, " yes |");
+ else
+ len += snprintf(buf+len, sizeof(buf)-len, " no |");
+
+ len += snprintf(buf+len, sizeof(buf)-len,
+ " Turbo-A disabled:");
+ if (AR5K_EEPROM_HDR_T_2GHZ_DIS(ee.ee_header))
+ len += snprintf(buf+len, sizeof(buf)-len, " yes |\n");
+ else
+ len += snprintf(buf+len, sizeof(buf)-len, " no |\n");
+
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| 802.11b Support: ");
+ if (AR5K_EEPROM_HDR_11B(ee.ee_header))
+ len += snprintf(buf+len, sizeof(buf)-len, " yes |");
+ else
+ len += snprintf(buf+len, sizeof(buf)-len, " no |");
+
+ len += snprintf(buf+len, sizeof(buf)-len,
+ " Turbo-G disabled:");
+ if (AR5K_EEPROM_HDR_T_2GHZ_DIS(ee.ee_header))
+ len += snprintf(buf+len, sizeof(buf)-len, " yes |\n");
+ else
+ len += snprintf(buf+len, sizeof(buf)-len, " no |\n");
+
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| 802.11g Support: ");
+ if (AR5K_EEPROM_HDR_11G(ee.ee_header))
+ len += snprintf(buf+len, sizeof(buf)-len, " yes |");
+ else
+ len += snprintf(buf+len, sizeof(buf)-len, " no |");
+
+ len += snprintf(buf+len, sizeof(buf)-len,
+ " 2GHz XR disabled:");
+ if (AR5K_EEPROM_HDR_XR2_DIS(ee.ee_misc0))
+ len += snprintf(buf+len, sizeof(buf)-len, " yes |\n");
+ else
+ len += snprintf(buf+len, sizeof(buf)-len, " no |\n");
+
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| RFKill Support: ");
+ if (AR5K_EEPROM_HDR_RFKILL(ee.ee_header))
+ len += snprintf(buf+len, sizeof(buf)-len, " yes |");
+ else
+ len += snprintf(buf+len, sizeof(buf)-len, " no |");
+
+ len += snprintf(buf+len, sizeof(buf)-len,
+ " 5GHz XR disabled:");
+ if (AR5K_EEPROM_HDR_XR5_DIS(ee.ee_misc0))
+ len += snprintf(buf+len, sizeof(buf)-len, " yes |\n");
+ else
+ len += snprintf(buf+len, sizeof(buf)-len, " no |\n");
+
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| 32kHz Crystal: ");
+ if (AR5K_EEPROM_HAS32KHZCRYSTAL(ee.ee_misc1) ||
+ AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(ee.ee_misc1)) {
+ len += snprintf(buf+len, sizeof(buf)-len, " yes |");
+ } else {
+ len += snprintf(buf+len, sizeof(buf)-len, " no |");
+ }
+
+ len += snprintf(buf+len, sizeof(buf)-len,
+ " HW Comp disabled:");
+ if (AR5K_EEPROM_COMP_DIS(ee.ee_misc5))
+ len += snprintf(buf+len, sizeof(buf)-len, " yes |\n");
+ else
+ len += snprintf(buf+len, sizeof(buf)-len, " no |\n");
+
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| AES Enc disabled: ");
+ if (AR5K_EEPROM_AES_DIS(ee.ee_misc5))
+ len += snprintf(buf+len, sizeof(buf)-len, " yes |");
+ else
+ len += snprintf(buf+len, sizeof(buf)-len, " no |");
+
+ len += snprintf(buf+len, sizeof(buf)-len,
+ " FastFrm disabled:");
+ if (AR5K_EEPROM_FF_DIS(ee.ee_misc5))
+ len += snprintf(buf+len, sizeof(buf)-len, " yes |\n");
+ else
+ len += snprintf(buf+len, sizeof(buf)-len, " no |\n");
+
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| Bursting disabled:");
+ if (AR5K_EEPROM_BURST_DIS(ee.ee_misc5))
+ len += snprintf(buf+len, sizeof(buf)-len, " yes |");
+ else
+ len += snprintf(buf+len, sizeof(buf)-len, " no |");
+
+ len += snprintf(buf+len, sizeof(buf)-len,
+ " Max avail QCU: ");
+ len += snprintf(buf+len, sizeof(buf)-len, " %3i |\n",
+ AR5K_EEPROM_MAX_QCU(ee.ee_misc5));
+
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| Heavy Clip enable:");
+ if (AR5K_EEPROM_HEAVY_CLIP_EN(ee.ee_misc5))
+ len += snprintf(buf+len, sizeof(buf)-len, " yes |");
+ else
+ len += snprintf(buf+len, sizeof(buf)-len, " no |");
+
+ len += snprintf(buf+len, sizeof(buf)-len,
+ " Keycache size: ");
+ len += snprintf(buf+len, sizeof(buf)-len, " %3i |\n",
+ AR5K_EEPROM_KEY_CACHE_SIZE(ee.ee_misc5));
+
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "\\================================================/\n\n");
+
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "/====[Calibration data common for all modes]====\\\n");
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| |\n");
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| CCK/OFDM gain delta: %2i |\n",
+ ee.ee_cck_ofdm_gain_delta);
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| CCK/OFDM power delta: %2i |\n",
+ ee.ee_cck_ofdm_power_delta);
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| Scaled CCK delta: %2i |\n",
+ ee.ee_scaled_cck_delta);
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| 2GHz Antenna gain: %2i |\n",
+ AR5K_EEPROM_ANT_GAIN_2GHZ(ee.ee_ant_gain));
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| 5GHz Antenna gain: %2i |\n",
+ AR5K_EEPROM_ANT_GAIN_5GHZ(ee.ee_ant_gain));
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| Turbo 2W maximum dBm: %2i |\n",
+ AR5K_EEPROM_HDR_T_5GHZ_DBM(ee.ee_header));
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| Target power start: 0x%03x |\n",
+ AR5K_EEPROM_TARGET_PWRSTART(ee.ee_misc1));
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| EAR Start: 0x%03x |\n",
+ AR5K_EEPROM_EARSTART(ee.ee_misc0));
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| |\n");
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "\\===============================================/\n");
+
+ len = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+
+ return len;
+}
+
+static const struct file_operations fops_ee_header = {
+ .read = read_file_eeprom_header,
+ .open = ath5k_debugfs_open,
+ .owner = THIS_MODULE,
+};
+
+/* EEPROM Header (per mode) */
+static unsigned int dump_calinfo_for_mode(struct ath5k_hw *ah, int mode,
+ char __user *user_buf, size_t count, loff_t *ppos)
+{
+ struct ath5k_eeprom_info ee = ah->ah_capabilities.cap_eeprom;
+ unsigned int len = 0;
+ char buf[2000];
+ int i;
+
+ if ((!AR5K_EEPROM_HDR_11A(ee.ee_header) && (mode == AR5K_EEPROM_MODE_11A))
+ || (!AR5K_EEPROM_HDR_11B(ee.ee_header) && (mode == AR5K_EEPROM_MODE_11B))
+ || (!AR5K_EEPROM_HDR_11G(ee.ee_header) && (mode == AR5K_EEPROM_MODE_11G))) {
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "Mode not available for your card\n");
+ len = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ return len;
+ }
+
+
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "/=========================================================\\\n");
+
+ if (mode == AR5K_EEPROM_MODE_11A)
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| Calibration data for 802.11a |\n");
+
+ if (mode == AR5K_EEPROM_MODE_11B)
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| Calibration data for 802.11b |\n");
+
+ if (mode == AR5K_EEPROM_MODE_11G)
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| Calibration data for 802.11g |\n");
+
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "|=========================================================|\n");
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| I power: 0x%02x | Q power: 0x%02x |\n",
+ ee.ee_i_cal[mode], ee.ee_q_cal[mode]);
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| Use fixed bias: 0x%02x | Max turbo power: 0x%02x |\n",
+ ee.ee_fixed_bias[mode], ee.ee_turbo_max_power[mode]);
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| Max XR power: 0x%02x | Switch Settling Time: 0x%02x |\n",
+ ee.ee_xr_power[mode], ee.ee_switch_settling[mode]);
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| Tx/Rx attenuation: 0x%02x | TX end to XLNA On: 0x%02x |\n",
+ ee.ee_atn_tx_rx[mode], ee.ee_tx_end2xlna_enable[mode]);
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| TX end to XPA Off: 0x%02x | TX end to XPA On: 0x%02x |\n",
+ ee.ee_tx_end2xpa_disable[mode], ee.ee_tx_frm2xpa_enable[mode]);
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| 62db Threshold: 0x%02x | XLNA gain: 0x%02x |\n",
+ ee.ee_thr_62[mode], ee.ee_xlna_gain[mode]);
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| XPD: 0x%02x | XPD gain: 0x%02x |\n",
+ ee.ee_xpd[mode], ee.ee_x_gain[mode]);
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| I gain: 0x%02x | Tx/Rx margin: 0x%02x |\n",
+ ee.ee_i_gain[mode], ee.ee_margin_tx_rx[mode]);
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| False detect backoff: 0x%02x | Noise Floor Threshold: %3d |\n",
+ ee.ee_false_detect[mode], ee.ee_noise_floor_thr[mode]);
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| ADC desired size: %3d | PGA desired size: %3d |\n",
+ ee.ee_adc_desired_size[mode], ee.ee_pga_desired_size[mode]);
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "|=========================================================|\n");
+ for (i = 0; i < AR5K_EEPROM_N_PCDAC; i++) {
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| Antenna control %2i: 0x%02x |", i,
+ ee.ee_ant_control[mode][i]);
+ i++;
+ len += snprintf(buf+len, sizeof(buf)-len,
+ " Antenna control %2i: 0x%02x |\n", i,
+ ee.ee_ant_control[mode][i]);
+ }
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "|=========================================================|\n");
+ for (i = 0; i < AR5K_EEPROM_N_OBDB; i++) {
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| Output Bias current %i: %2i |", i,
+ ee.ee_ob[mode][i]);
+ len += snprintf(buf+len, sizeof(buf)-len,
+ " Driver Bias current %i: %2i |\n", i,
+ ee.ee_db[mode][i]);
+ }
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "\\=========================================================/\n");
+
+ if (ee.ee_version >= AR5K_EEPROM_VERSION_5_0 &&
+ (mode == AR5K_EEPROM_MODE_11A || mode == AR5K_EEPROM_MODE_11G)) {
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "/==================== Turbo mode infos ===================\\\n");
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| Switch Settling time: 0x%02x | Tx/Rx margin: 0x%02x |\n",
+ ee.ee_switch_settling_turbo[mode], ee.ee_margin_tx_rx_turbo[mode]);
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| Tx/Rx attenuation: 0x%02x | ADC desired size: %3d |\n",
+ ee.ee_atn_tx_rx_turbo[mode], ee.ee_adc_desired_size_turbo[mode]);
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| PGA desired size: %3d | |\n",
+ ee.ee_pga_desired_size_turbo[mode]);
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "\\=========================================================/\n");
+ }
+
+ len = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ return len;
+}
+
+static ssize_t read_file_eeprom_header_11a(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath5k_softc *sc = file->private_data;
+ struct ath5k_hw *ah = sc->ah;
+ unsigned int len = 0;
+
+ len = dump_calinfo_for_mode(ah, AR5K_EEPROM_MODE_11A, user_buf, count, ppos);
+ return len;
+}
+
+static ssize_t read_file_eeprom_header_11b(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath5k_softc *sc = file->private_data;
+ struct ath5k_hw *ah = sc->ah;
+ unsigned int len = 0;
+
+ len = dump_calinfo_for_mode(ah, AR5K_EEPROM_MODE_11B, user_buf, count, ppos);
+ return len;
+}
+
+static ssize_t read_file_eeprom_header_11g(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath5k_softc *sc = file->private_data;
+ struct ath5k_hw *ah = sc->ah;
+ unsigned int len = 0;
+
+ len = dump_calinfo_for_mode(ah, AR5K_EEPROM_MODE_11G, user_buf, count, ppos);
+ return len;
+}
+
+static const struct file_operations fops_ee_header_11a = {
+ .read = read_file_eeprom_header_11a,
+ .open = ath5k_debugfs_open,
+ .owner = THIS_MODULE,
+};
+
+static const struct file_operations fops_ee_header_11b = {
+ .read = read_file_eeprom_header_11b,
+ .open = ath5k_debugfs_open,
+ .owner = THIS_MODULE,
+};
+
+static const struct file_operations fops_ee_header_11g = {
+ .read = read_file_eeprom_header_11g,
+ .open = ath5k_debugfs_open,
+ .owner = THIS_MODULE,
+};
+
+
+/* EEPROM channel power calibration info (per mode) */
+static unsigned int dump_pcalinfo_for_mode_rf5111(struct ath5k_hw *ah, int mode,
+ char __user *user_buf, size_t count, loff_t *ppos)
+{
+ struct ath5k_eeprom_info ee = ah->ah_capabilities.cap_eeprom;
+ struct ath5k_chan_pcal_info *gen_chan_info;
+ struct ath5k_chan_pcal_info_rf5111 *chan_pcal_info;
+ unsigned int len = 0;
+ char buf[4000];
+ u_int16_t cal_piers;
+ int i, c;
+
+ if ((!AR5K_EEPROM_HDR_11A(ee.ee_header) && (mode == AR5K_EEPROM_MODE_11A))
+ || (!AR5K_EEPROM_HDR_11B(ee.ee_header) && (mode == AR5K_EEPROM_MODE_11B))
+ || (!AR5K_EEPROM_HDR_11G(ee.ee_header) && (mode == AR5K_EEPROM_MODE_11G))) {
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "Mode not available for your card\n");
+ len = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ return len;
+ }
+
+ switch (mode) {
+ case AR5K_EEPROM_MODE_11A:
+ gen_chan_info = ee.ee_pwr_cal_a;
+ cal_piers = ee.ee_n_piers[mode];
+ break;
+ case AR5K_EEPROM_MODE_11B:
+ gen_chan_info = ee.ee_pwr_cal_b;
+ cal_piers = ee.ee_n_piers[mode];
+ break;
+ case AR5K_EEPROM_MODE_11G:
+ gen_chan_info = ee.ee_pwr_cal_g;
+ cal_piers = ee.ee_n_piers[mode];
+ break;
+ default:
+ return len;
+ }
+
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "/=============================== Per channel power calibration ================================\\\n");
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| Freq | pwr_0 | pwr_1 | pwr_2 | pwr_3 | pwr_4 | pwr_5 | pwr_6 | pwr_7 | pwr_8 | pwr_9 | pwr10 |\n");
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| | pcdac | pcdac | pcdac | pcdac | pcdac | pcdac | pcdac | pcdac | pcdac | pcdac | pcdac |\n");
+
+ for (i = 0; i < cal_piers; i++) {
+ chan_pcal_info = &gen_chan_info[i].rf5111_info;
+
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "|======|=======|=======|=======|=======|=======|=======|=======|=======|=======|=======|=======|\n");
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| %4i |", gen_chan_info[i].freq);
+ if (ee.ee_version <= AR5K_EEPROM_VERSION_3_3) {
+ for (c = 0; c < AR5K_EEPROM_N_PWR_POINTS_5111; c++) {
+ len += snprintf(buf+len, sizeof(buf)-len,
+ " %2i.%02i |", chan_pcal_info->pwr[c] / 2,
+ chan_pcal_info->pwr[c] % 2 * 50);
+ }
+
+ len += snprintf(buf+len, sizeof(buf)-len, "\n| |");
+ } else {
+ for (c = 0; c < AR5K_EEPROM_N_PWR_POINTS_5111; c++) {
+ len += snprintf(buf+len, sizeof(buf)-len,
+ " %2i.%02i |", chan_pcal_info->pwr[c] / 4,
+ chan_pcal_info->pwr[c] % 4 * 25);
+ }
+
+ len += snprintf(buf+len, sizeof(buf)-len, "\n| |");
+ }
+
+ for (c = 0; c < AR5K_EEPROM_N_PWR_POINTS_5111; c++) {
+ len += snprintf(buf+len, sizeof(buf)-len, " [%2i]",
+ chan_pcal_info->pcdac[c]);
+ len += snprintf(buf+len, sizeof(buf)-len, " |");
+ }
+
+ len += snprintf(buf+len, sizeof(buf)-len, "\n");
+
+ }
+
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "\\==============================================================================================/\n");
+ len = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ return len;
+}
+
+static unsigned int dump_pcalinfo_for_mode_rf5112(struct ath5k_hw *ah, int mode,
+ char __user *user_buf, size_t count, loff_t *ppos)
+{
+ struct ath5k_eeprom_info ee = ah->ah_capabilities.cap_eeprom;
+ struct ath5k_chan_pcal_info *gen_chan_info;
+ struct ath5k_chan_pcal_info_rf5112 *chan_pcal_info;
+ unsigned int len = 0;
+ char buf[4000];
+ u_int16_t cal_piers;
+ int i, c;
+
+ if ((!AR5K_EEPROM_HDR_11A(ee.ee_header) && (mode == AR5K_EEPROM_MODE_11A))
+ || (!AR5K_EEPROM_HDR_11B(ee.ee_header) && (mode == AR5K_EEPROM_MODE_11B))
+ || (!AR5K_EEPROM_HDR_11G(ee.ee_header) && (mode == AR5K_EEPROM_MODE_11G))) {
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "Mode not available for your card\n");
+ len = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ return len;
+ }
+
+ switch (mode) {
+ case AR5K_EEPROM_MODE_11A:
+ gen_chan_info = ee.ee_pwr_cal_a;
+ cal_piers = ee.ee_n_piers[mode];
+ break;
+ case AR5K_EEPROM_MODE_11B:
+ gen_chan_info = ee.ee_pwr_cal_b;
+ cal_piers = ee.ee_n_piers[mode];
+ break;
+ case AR5K_EEPROM_MODE_11G:
+ gen_chan_info = ee.ee_pwr_cal_g;
+ cal_piers = ee.ee_n_piers[mode];
+ break;
+ default:
+ return len;
+ }
+
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "/=================== Per channel power calibration ====================\\\n");
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| Freq | pwr_0 | pwr_1 | pwr_2 | pwr_3 |pwrx3_0|pwrx3_1|pwrx3_2|max_pwr|\n");
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| | pcdac | pcdac | pcdac | pcdac | pcdac | pcdac | pcdac | |\n");
+
+ for (i = 0; i < cal_piers; i++) {
+
+ chan_pcal_info = &gen_chan_info[i].rf5112_info;
+
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "|======|=======|=======|=======|=======|=======|=======|=======|=======|\n");
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| %4i |", gen_chan_info[i].freq);
+
+ for (c = 0; c < AR5K_EEPROM_N_XPD0_POINTS; c++) {
+ len += snprintf(buf+len, sizeof(buf)-len,
+ " %2i.%02i |", chan_pcal_info->pwr_x0[c] / 4,
+ chan_pcal_info->pwr_x0[c] % 4 * 25);
+ }
+
+ for (c = 0; c < AR5K_EEPROM_N_XPD3_POINTS; c++) {
+ len += snprintf(buf+len, sizeof(buf)-len,
+ " %2i.%02i |", chan_pcal_info->pwr_x3[c] / 4,
+ chan_pcal_info->pwr_x3[c] % 4 * 25);
+ }
+
+ len += snprintf(buf+len, sizeof(buf)-len,
+ " %2i.%02i |\n", gen_chan_info[i].max_pwr / 4,
+ gen_chan_info[i].max_pwr % 4 * 25);
+
+ len += snprintf(buf+len, sizeof(buf)-len, "| |");
+
+ for (c = 0; c < AR5K_EEPROM_N_XPD0_POINTS; c++) {
+ len += snprintf(buf+len, sizeof(buf)-len, " [%2i]",
+ chan_pcal_info->pcdac_x0[c]);
+ len += snprintf(buf+len, sizeof(buf)-len,
+ " |");
+ }
+
+ for (c = 0; c < AR5K_EEPROM_N_XPD3_POINTS; c++) {
+ len += snprintf(buf+len, sizeof(buf)-len, " [%2i]",
+ chan_pcal_info->pcdac_x3[c]);
+ len += snprintf(buf+len, sizeof(buf)-len,
+ " |");
+ }
+
+ len += snprintf(buf+len, sizeof(buf)-len, " |\n");
+
+ }
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "\\======================================================================/\n");
+ len = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ return len;
+}
+
+static unsigned int dump_pcalinfo_for_mode_rf2413(struct ath5k_hw *ah, int mode,
+ char __user *user_buf, size_t count, loff_t *ppos)
+{
+ struct ath5k_eeprom_info ee = ah->ah_capabilities.cap_eeprom;
+ struct ath5k_chan_pcal_info *gen_chan_info;
+ struct ath5k_chan_pcal_info_rf2413 *chan_pcal_info;
+ unsigned int len = 0;
+ char buf[4000];
+ u_int16_t cal_piers;
+ int i, c;
+
+ if ((!AR5K_EEPROM_HDR_11A(ee.ee_header) && (mode == AR5K_EEPROM_MODE_11A))
+ || (!AR5K_EEPROM_HDR_11B(ee.ee_header) && (mode == AR5K_EEPROM_MODE_11B))
+ || (!AR5K_EEPROM_HDR_11G(ee.ee_header) && (mode == AR5K_EEPROM_MODE_11G))) {
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "Mode not available for your card\n");
+ len = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ return len;
+ }
+
+ switch (mode) {
+ case AR5K_EEPROM_MODE_11A:
+ gen_chan_info = ee.ee_pwr_cal_a;
+ cal_piers = ee.ee_n_piers[mode];
+ break;
+ case AR5K_EEPROM_MODE_11B:
+ gen_chan_info = ee.ee_pwr_cal_b;
+ cal_piers = ee.ee_n_piers[mode];
+ break;
+ case AR5K_EEPROM_MODE_11G:
+ gen_chan_info = ee.ee_pwr_cal_g;
+ cal_piers = ee.ee_n_piers[mode];
+ break;
+ default:
+ return len;
+ }
+
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "/====================== Per channel power calibration ===================\\\n");
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| Freq | pwr_i | pwr_0 | pwr_1 | pwr_2 | pwr_3 |\n");
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| | pddac_i | pddac_0 | pddac_1 | pddac_2 | pddac_3 |\n");
+
+ for (i = 0; i < cal_piers; i++) {
+
+ chan_pcal_info = &gen_chan_info[i].rf2413_info;
+
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "|======|=========|=============|=============|=============|=============|\n");
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| %4i | | | | | |\n",
+ gen_chan_info[i].freq);
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "|------|---------|-------------|-------------|-------------|-------------|\n");
+ for (c = 0; c < ee.ee_pd_gains[mode]; c++) {
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| | %2i | %2i.%02i | %2i.%02i | %2i.%02i | %2i.%02i |\n",
+ chan_pcal_info->pwr_i[c],
+ chan_pcal_info->pwr[c][0] / 2,
+ chan_pcal_info->pwr[c][0] % 2 * 50,
+ chan_pcal_info->pwr[c][1] / 2,
+ chan_pcal_info->pwr[c][1] % 2 * 50,
+ chan_pcal_info->pwr[c][2] / 2,
+ chan_pcal_info->pwr[c][2] % 2 * 50,
+ chan_pcal_info->pwr[c][3] / 2,
+ chan_pcal_info->pwr[c][3] % 2 * 50);
+
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| | %3i | %3i | %3i | %3i | %3i |\n",
+ chan_pcal_info->pddac_i[c],
+ chan_pcal_info->pddac[c][0],
+ chan_pcal_info->pddac[c][1],
+ chan_pcal_info->pddac[c][2],
+ chan_pcal_info->pddac[c][3]);
+
+ if (c < ee.ee_pd_gains[mode] - 1)
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "|------|---------|-------------|-------------|-------------|-------------|\n");
+ }
+ }
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "\\========================================================================/\n");
+ len = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ return len;
+}
+
+static ssize_t read_file_eeprom_pcalinfo_11a(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath5k_softc *sc = file->private_data;
+ struct ath5k_hw *ah = sc->ah;
+ unsigned int len = 0;
+
+ switch (ah->ah_radio) {
+ case AR5K_RF5111:
+ len = dump_pcalinfo_for_mode_rf5111(ah, AR5K_EEPROM_MODE_11A,
+ user_buf, count, ppos);
+ break;
+ case AR5K_RF5112:
+ len = dump_pcalinfo_for_mode_rf5112(ah, AR5K_EEPROM_MODE_11A,
+ user_buf, count, ppos);
+ break;
+ case AR5K_RF2413:
+ case AR5K_RF5413:
+ case AR5K_RF2425:
+ len = dump_pcalinfo_for_mode_rf2413(ah, AR5K_EEPROM_MODE_11A,
+ user_buf, count, ppos);
+ break;
+ default:
+ return 0;
+ }
+
+ return len;
+}
+
+static ssize_t read_file_eeprom_pcalinfo_11b(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath5k_softc *sc = file->private_data;
+ struct ath5k_hw *ah = sc->ah;
+ unsigned int len = 0;
+
+ switch (ah->ah_radio) {
+ case AR5K_RF5111:
+ len = dump_pcalinfo_for_mode_rf5111(ah, AR5K_EEPROM_MODE_11B, user_buf, count, ppos);
+ break;
+ case AR5K_RF5112:
+ len = dump_pcalinfo_for_mode_rf5112(ah, AR5K_EEPROM_MODE_11B, user_buf, count, ppos);
+ break;
+ case AR5K_RF2413:
+ case AR5K_RF5413:
+ case AR5K_RF2425:
+ len = dump_pcalinfo_for_mode_rf2413(ah, AR5K_EEPROM_MODE_11B, user_buf, count, ppos);
+ break;
+ default:
+ return 0;
+ }
+
+ return len;
+}
+
+static ssize_t read_file_eeprom_pcalinfo_11g(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath5k_softc *sc = file->private_data;
+ struct ath5k_hw *ah = sc->ah;
+ unsigned int len = 0;
+
+ switch (ah->ah_radio) {
+ case AR5K_RF5111:
+ len = dump_pcalinfo_for_mode_rf5111(ah, AR5K_EEPROM_MODE_11G, user_buf, count, ppos);
+ break;
+ case AR5K_RF5112:
+ len = dump_pcalinfo_for_mode_rf5112(ah, AR5K_EEPROM_MODE_11G, user_buf, count, ppos);
+ break;
+ case AR5K_RF2413:
+ case AR5K_RF5413:
+ case AR5K_RF2425:
+ len = dump_pcalinfo_for_mode_rf2413(ah, AR5K_EEPROM_MODE_11G, user_buf, count, ppos);
+ break;
+ default:
+ return 0;
+ }
+
+ return len;
+}
+
+static const struct file_operations fops_ee_pcalinfo_11a = {
+ .read = read_file_eeprom_pcalinfo_11a,
+ .open = ath5k_debugfs_open,
+ .owner = THIS_MODULE,
+};
+
+static const struct file_operations fops_ee_pcalinfo_11b = {
+ .read = read_file_eeprom_pcalinfo_11b,
+ .open = ath5k_debugfs_open,
+ .owner = THIS_MODULE,
+};
+
+static const struct file_operations fops_ee_pcalinfo_11g = {
+ .read = read_file_eeprom_pcalinfo_11g,
+ .open = ath5k_debugfs_open,
+ .owner = THIS_MODULE,
+};
+
+/* EEPROM Per rate power calibration info */
+static unsigned int dump_rate_calinfo_for_mode(struct ath5k_hw *ah, int mode,
+ char __user *user_buf, size_t count, loff_t *ppos)
+{
+ struct ath5k_eeprom_info ee = ah->ah_capabilities.cap_eeprom;
+ struct ath5k_rate_pcal_info *rate_pcal_info;
+ u_int16_t rate_target_pwr_num;
+ unsigned int len = 0;
+ char buf[2000];
+ int i;
+
+ if ((!AR5K_EEPROM_HDR_11A(ee.ee_header) && (mode == AR5K_EEPROM_MODE_11A))
+ || (!AR5K_EEPROM_HDR_11B(ee.ee_header) && (mode == AR5K_EEPROM_MODE_11B))
+ || (!AR5K_EEPROM_HDR_11G(ee.ee_header) && (mode == AR5K_EEPROM_MODE_11G))) {
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "Mode not available for your card\n");
+ len = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ return len;
+ }
+
+ switch (mode) {
+ case AR5K_EEPROM_MODE_11A:
+ rate_pcal_info = ee.ee_rate_tpwr_a;
+ rate_target_pwr_num = ee.ee_rate_target_pwr_num[mode];
+ break;
+ case AR5K_EEPROM_MODE_11B:
+ rate_pcal_info = ee.ee_rate_tpwr_b;
+ rate_target_pwr_num = ee.ee_rate_target_pwr_num[mode];
+ break;
+ case AR5K_EEPROM_MODE_11G:
+ rate_pcal_info = ee.ee_rate_tpwr_g;
+ rate_target_pwr_num = ee.ee_rate_target_pwr_num[mode];
+ break;
+ default:
+ return 0;
+ }
+
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "/============== Per rate power calibration ===========\\\n");
+ if (mode == AR5K_EEPROM_MODE_11B)
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| Freq | 1Mbit/s | 2Mbit/s | 5.5Mbit/s | 11Mbit/s |\n");
+ else
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| Freq | 6-24Mbit/s | 36Mbit/s | 48Mbit/s | 54Mbit/s |\n");
+
+ for (i = 0; i < rate_target_pwr_num; i++) {
+
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "|======|============|==========|===========|==========|\n");
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "| %4i |", rate_pcal_info[i].freq);
+ len += snprintf(buf+len, sizeof(buf)-len,
+ " %2i.%02i |", rate_pcal_info[i].target_power_6to24 / 2,
+ rate_pcal_info[i].target_power_6to24 % 2);
+ len += snprintf(buf+len, sizeof(buf)-len,
+ " %2i.%02i |", rate_pcal_info[i].target_power_36 / 2,
+ rate_pcal_info[i].target_power_36 % 2);
+ len += snprintf(buf+len, sizeof(buf)-len,
+ " %2i.%02i |", rate_pcal_info[i].target_power_48 / 2,
+ rate_pcal_info[i].target_power_48 % 2);
+ len += snprintf(buf+len, sizeof(buf)-len,
+ " %2i.%02i |\n", rate_pcal_info[i].target_power_54 / 2,
+ rate_pcal_info[i].target_power_54 % 2);
+ }
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "\\=====================================================/\n");
+ len = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ return len;
+}
+
+static ssize_t read_file_rate_pcalinfo_11a(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath5k_softc *sc = file->private_data;
+ struct ath5k_hw *ah = sc->ah;
+ unsigned int len = 0;
+
+ len = dump_rate_calinfo_for_mode(ah, AR5K_EEPROM_MODE_11A, user_buf, count, ppos);
+ return len;
+}
+
+static ssize_t read_file_rate_pcalinfo_11b(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath5k_softc *sc = file->private_data;
+ struct ath5k_hw *ah = sc->ah;
+ unsigned int len = 0;
+
+ len = dump_rate_calinfo_for_mode(ah, AR5K_EEPROM_MODE_11B, user_buf, count, ppos);
+ return len;
+}
+
+static ssize_t read_file_rate_pcalinfo_11g(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath5k_softc *sc = file->private_data;
+ struct ath5k_hw *ah = sc->ah;
+ unsigned int len = 0;
+
+ len = dump_rate_calinfo_for_mode(ah, AR5K_EEPROM_MODE_11G, user_buf, count, ppos);
+ return len;
+}
+
+static const struct file_operations fops_ee_rate_pcalinfo_11a = {
+ .read = read_file_rate_pcalinfo_11a,
+ .open = ath5k_debugfs_open,
+ .owner = THIS_MODULE,
+};
+
+static const struct file_operations fops_ee_rate_pcalinfo_11b = {
+ .read = read_file_rate_pcalinfo_11b,
+ .open = ath5k_debugfs_open,
+ .owner = THIS_MODULE,
+};
+
+static const struct file_operations fops_ee_rate_pcalinfo_11g = {
+ .read = read_file_rate_pcalinfo_11g,
+ .open = ath5k_debugfs_open,
+ .owner = THIS_MODULE,
+};
/* debugfs: debug level */
@@ -426,6 +1278,36 @@ ath5k_debug_init_device(struct ath5k_softc *sc)
sc->debug.debugfs_tsf = debugfs_create_file("tsf", S_IWUSR | S_IRUGO,
sc->debug.debugfs_phydir, sc, &fops_tsf);
+ sc->debug.debugfs_ee_header = debugfs_create_file("eeprom_header", S_IRUGO,
+ sc->debug.debugfs_phydir, sc, &fops_ee_header);
+
+ sc->debug.debugfs_ee_header_11a = debugfs_create_file("eeprom_header_11a", S_IRUGO,
+ sc->debug.debugfs_phydir, sc, &fops_ee_header_11a);
+
+ sc->debug.debugfs_ee_header_11b = debugfs_create_file("eeprom_header_11b", S_IRUGO,
+ sc->debug.debugfs_phydir, sc, &fops_ee_header_11b);
+
+ sc->debug.debugfs_ee_header_11g = debugfs_create_file("eeprom_header_11g", S_IRUGO,
+ sc->debug.debugfs_phydir, sc, &fops_ee_header_11g);
+
+ sc->debug.debugfs_ee_pcalinfo_11a = debugfs_create_file("eeprom_chan_pcalinfo_11a", S_IRUGO,
+ sc->debug.debugfs_phydir, sc, &fops_ee_pcalinfo_11a);
+
+ sc->debug.debugfs_ee_pcalinfo_11b = debugfs_create_file("eeprom_chan_pcalinfo_11b", S_IRUGO,
+ sc->debug.debugfs_phydir, sc, &fops_ee_pcalinfo_11b);
+
+ sc->debug.debugfs_ee_pcalinfo_11g = debugfs_create_file("eeprom_chan_pcalinfo_11g", S_IRUGO,
+ sc->debug.debugfs_phydir, sc, &fops_ee_pcalinfo_11g);
+
+ sc->debug.debugfs_ee_rate_pcalinfo_11a = debugfs_create_file("eeprom_rate_pcalinfo_11a", S_IRUGO,
+ sc->debug.debugfs_phydir, sc, &fops_ee_rate_pcalinfo_11a);
+
+ sc->debug.debugfs_ee_rate_pcalinfo_11b = debugfs_create_file("eeprom_rate_pcalinfo_11b", S_IRUGO,
+ sc->debug.debugfs_phydir, sc, &fops_ee_rate_pcalinfo_11b);
+
+ sc->debug.debugfs_ee_rate_pcalinfo_11g = debugfs_create_file("eeprom_rate_pcalinfo_11g", S_IRUGO,
+ sc->debug.debugfs_phydir, sc, &fops_ee_rate_pcalinfo_11g);
+
sc->debug.debugfs_beacon = debugfs_create_file("beacon", S_IWUSR | S_IRUGO,
sc->debug.debugfs_phydir, sc, &fops_beacon);
@@ -446,6 +1328,16 @@ ath5k_debug_finish_device(struct ath5k_softc *sc)
debugfs_remove(sc->debug.debugfs_registers);
debugfs_remove(sc->debug.debugfs_tsf);
debugfs_remove(sc->debug.debugfs_beacon);
+ debugfs_remove(sc->debug.debugfs_ee_header);
+ debugfs_remove(sc->debug.debugfs_ee_header_11a);
+ debugfs_remove(sc->debug.debugfs_ee_header_11b);
+ debugfs_remove(sc->debug.debugfs_ee_header_11g);
+ debugfs_remove(sc->debug.debugfs_ee_pcalinfo_11a);
+ debugfs_remove(sc->debug.debugfs_ee_pcalinfo_11b);
+ debugfs_remove(sc->debug.debugfs_ee_pcalinfo_11g);
+ debugfs_remove(sc->debug.debugfs_ee_rate_pcalinfo_11a);
+ debugfs_remove(sc->debug.debugfs_ee_rate_pcalinfo_11b);
+ debugfs_remove(sc->debug.debugfs_ee_rate_pcalinfo_11g);
debugfs_remove(sc->debug.debugfs_reset);
debugfs_remove(sc->debug.debugfs_phydir);
}
diff --git a/drivers/net/wireless/ath5k/debug.h b/drivers/net/wireless/ath5k/debug.h
index ffc5293..c5c88d8 100644
--- a/drivers/net/wireless/ath5k/debug.h
+++ b/drivers/net/wireless/ath5k/debug.h
@@ -73,6 +73,16 @@ struct ath5k_dbg_info {
struct dentry *debugfs_debug;
struct dentry *debugfs_registers;
struct dentry *debugfs_tsf;
+ struct dentry *debugfs_ee_header;
+ struct dentry *debugfs_ee_header_11a;
+ struct dentry *debugfs_ee_header_11b;
+ struct dentry *debugfs_ee_header_11g;
+ struct dentry *debugfs_ee_pcalinfo_11a;
+ struct dentry *debugfs_ee_pcalinfo_11b;
+ struct dentry *debugfs_ee_pcalinfo_11g;
+ struct dentry *debugfs_ee_rate_pcalinfo_11a;
+ struct dentry *debugfs_ee_rate_pcalinfo_11b;
+ struct dentry *debugfs_ee_rate_pcalinfo_11g;
struct dentry *debugfs_beacon;
struct dentry *debugfs_reset;
};
Nick Kossifidis wrote:
> * Add debug code for displaying EEPROM data. Tested on various chip combinations, on x86 and IXP43x (armv5te). It has many > 80cols warnings but i
> don't think it'll be more readable if i start breaking lines, it's already messy, after all it's debug code. This code also replaces ath_info tool.
I think breaking lines in this case would be rather contraproductive.
> Signed-Off-by: Nick Kossifidis <[email protected]>
>
> ---
> diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath5k/debug.c
> index ccaeb5c..f0ef5b3 100644
> --- a/drivers/net/wireless/ath5k/debug.c
> +++ b/drivers/net/wireless/ath5k/debug.c
> @@ -324,6 +324,858 @@ static const struct file_operations fops_reset = {
> .owner = THIS_MODULE,
> };
>
> +/* debugfs: EEPROM stuff */
> +
> +/* EEPROM Header (common) */
> +static ssize_t read_file_eeprom_header(struct file *file, char __user *user_buf,
> + size_t count, loff_t *ppos)
> +{
> +
> + struct ath5k_softc *sc = file->private_data;
> + struct ath5k_hw *ah = sc->ah;
> + struct ath5k_eeprom_info ee = ah->ah_capabilities.cap_eeprom;
> + char buf[2000];
Please don't use that much memory from stack. 2k is way too much. Note that
you use yet another bunch of stack (next 3k here on 64-bit) by
ath5k_eeprom_info and 32-bit x86 can still be configured with 4k stacks.
Convert both of them to dynamically allocated buffers.
> +/* EEPROM Header (per mode) */
> +static unsigned int dump_calinfo_for_mode(struct ath5k_hw *ah, int mode,
> + char __user *user_buf, size_t count, loff_t *ppos)
> +{
> + struct ath5k_eeprom_info ee = ah->ah_capabilities.cap_eeprom;
> + unsigned int len = 0;
> + char buf[2000];
dtto
> + int i;
...
> + len = simple_read_from_buffer(user_buf, count, ppos, buf, len);
simple_read_from_buffer can fail and returns negative errno in that case,
change dump_calinfo_for_mode return type appropriately.
> + return len;
> +}
...
> +/* EEPROM channel power calibration info (per mode) */
> +static unsigned int dump_pcalinfo_for_mode_rf5111(struct ath5k_hw *ah, int mode,
> + char __user *user_buf, size_t count, loff_t *ppos)
return ssize_t for the same reason
> +{
> + struct ath5k_eeprom_info ee = ah->ah_capabilities.cap_eeprom;
> + struct ath5k_chan_pcal_info *gen_chan_info;
> + struct ath5k_chan_pcal_info_rf5111 *chan_pcal_info;
> + unsigned int len = 0;
> + char buf[4000];
Here you are almost out of stack even on 8k stacks ;).
> +static unsigned int dump_pcalinfo_for_mode_rf5112(struct ath5k_hw *ah, int mode,
> + char __user *user_buf, size_t count, loff_t *ppos)
dtto and further too
> +{
> + struct ath5k_eeprom_info ee = ah->ah_capabilities.cap_eeprom;
> + struct ath5k_chan_pcal_info *gen_chan_info;
> + struct ath5k_chan_pcal_info_rf5112 *chan_pcal_info;
> + unsigned int len = 0;
> + char buf[4000];
dtto and further too
Happy new year!
Nick Kossifidis napsal(a):
> Hello Jiri and thanks a lot for the review ;-)
>
> 2009/1/4 Jiri Slaby <[email protected]>:
>>> +/* debugfs: EEPROM stuff */
>>> +
>>> +/* EEPROM Header (common) */
>>> +static ssize_t read_file_eeprom_header(struct file *file, char __user *user_buf,
>>> + size_t count, loff_t *ppos)
>>> +{
>>> +
>>> + struct ath5k_softc *sc = file->private_data;
>>> + struct ath5k_hw *ah = sc->ah;
>>> + struct ath5k_eeprom_info ee = ah->ah_capabilities.cap_eeprom;
>>> + char buf[2000];
>> Please don't use that much memory from stack. 2k is way too much. Note that
>> you use yet another bunch of stack (next 3k here on 64-bit) by
>> ath5k_eeprom_info and 32-bit x86 can still be configured with 4k stacks.
>>
>> Convert both of them to dynamically allocated buffers.
>>
>
> Why dynamically allocated buffers (can you point out some docs on
> these please ?) ? The length of each file (what we print) is standard.
> I understand that we use too much stack here but we can work this out
> eg. by using a pointer to ath5k_eeprom_info or something like that.
Yes, no problem in changing it to a pointer. Anyway the buf should be
kmalloc'ed anyway.
> I
> checked out user_buffer btw and it's 4K, sometimes it's not much for
> calibration data (eg. on RF5111 that we have 10 points per pd gain
> curve or RF2413+ that we can have multiple pd gain curves per
> channel).
I don't understand here. user_buf is sized by userspace application. E.g.
cat on my system requests user_buf of size 1K. simple_read_from_buffer()
takes care about multiple invocations of fops.read function by looking at
ppos parameter and filling user_buf by correct contents (some offset in from
param). BTW as a side-effect, it is possible, that the user will get
different info in these split reads.
>> dtto
>>
>
> What does dtto mean ?
Oops, as I checked right now, this shortcut is commonly used only in czech.
It should be detto or ditto (and it means "the same as above"), sorry for
the confusion.
"Nick Kossifidis" <[email protected]> writes:
>>> + struct ath5k_eeprom_info ee = ah->ah_capabilities.cap_eeprom;
>>> + unsigned int len = 0;
>>> + char buf[2000];
>>
>> dtto
>>
>
> What does dtto mean ?
A typo from ditto:
>From WordNet (r) 3.0 (2006) [wn]:
ditto
n 1: a mark used to indicate the word above it should be
repeated [syn: {ditto mark}, {ditto}]
v 1: repeat an action or statement; "The next speaker dittoed
her argument"
--
Kalle Valo
Hello Jiri and thanks a lot for the review ;-)
2009/1/4 Jiri Slaby <[email protected]>:
>> +/* debugfs: EEPROM stuff */
>> +
>> +/* EEPROM Header (common) */
>> +static ssize_t read_file_eeprom_header(struct file *file, char __user *user_buf,
>> + size_t count, loff_t *ppos)
>> +{
>> +
>> + struct ath5k_softc *sc = file->private_data;
>> + struct ath5k_hw *ah = sc->ah;
>> + struct ath5k_eeprom_info ee = ah->ah_capabilities.cap_eeprom;
>> + char buf[2000];
>
> Please don't use that much memory from stack. 2k is way too much. Note that
> you use yet another bunch of stack (next 3k here on 64-bit) by
> ath5k_eeprom_info and 32-bit x86 can still be configured with 4k stacks.
>
> Convert both of them to dynamically allocated buffers.
>
Why dynamically allocated buffers (can you point out some docs on
these please ?) ? The length of each file (what we print) is standard.
I understand that we use too much stack here but we can work this out
eg. by using a pointer to ath5k_eeprom_info or something like that. I
checked out user_buffer btw and it's 4K, sometimes it's not much for
calibration data (eg. on RF5111 that we have 10 points per pd gain
curve or RF2413+ that we can have multiple pd gain curves per
channel).
>> +/* EEPROM Header (per mode) */
>> +static unsigned int dump_calinfo_for_mode(struct ath5k_hw *ah, int mode,
>> + char __user *user_buf, size_t count, loff_t *ppos)
>> +{
>> + struct ath5k_eeprom_info ee = ah->ah_capabilities.cap_eeprom;
>> + unsigned int len = 0;
>> + char buf[2000];
>
> dtto
>
What does dtto mean ?
>> + int i;
> ...
>> + len = simple_read_from_buffer(user_buf, count, ppos, buf, len);
>
> simple_read_from_buffer can fail and returns negative errno in that case,
> change dump_calinfo_for_mode return type appropriately.
>
ACK
> Happy new year!
Thank you verry much, happy new year !! ;-)
--
GPG ID: 0xD21DB2DB
As you read this post global entropy rises. Have Fun ;-)
Nick