ath5k: improve pcal error handling for ENOMEM case
The ath5k driver does kmalloc allocations for pcal info in a loop. But, if one fails it was simply returning -ENOMEM without freeing already allocated memory. This patch corrects that oversight. Reported-by: Eugene A. Shatokhin <dame_eugene@mail.ru> Signed-off-by: John W. Linville <linville@tuxdriver.com> Reviewed-by: Bob Copeland <me@bobcopeland.com>
This commit is contained in:
parent
ba30c4a58c
commit
a065784620
1 changed files with 70 additions and 59 deletions
|
@ -660,6 +660,53 @@ ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp)
|
||||||
vp[i] = (ip[i] * max + (100 - ip[i]) * min) / 100;
|
vp[i] = (ip[i] * max + (100 - ip[i]) * min) / 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode)
|
||||||
|
{
|
||||||
|
struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
|
||||||
|
struct ath5k_chan_pcal_info *chinfo;
|
||||||
|
u8 pier, pdg;
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case AR5K_EEPROM_MODE_11A:
|
||||||
|
if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
|
||||||
|
return 0;
|
||||||
|
chinfo = ee->ee_pwr_cal_a;
|
||||||
|
break;
|
||||||
|
case AR5K_EEPROM_MODE_11B:
|
||||||
|
if (!AR5K_EEPROM_HDR_11B(ee->ee_header))
|
||||||
|
return 0;
|
||||||
|
chinfo = ee->ee_pwr_cal_b;
|
||||||
|
break;
|
||||||
|
case AR5K_EEPROM_MODE_11G:
|
||||||
|
if (!AR5K_EEPROM_HDR_11G(ee->ee_header))
|
||||||
|
return 0;
|
||||||
|
chinfo = ee->ee_pwr_cal_g;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
|
||||||
|
if (!chinfo[pier].pd_curves)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
|
||||||
|
struct ath5k_pdgain_info *pd =
|
||||||
|
&chinfo[pier].pd_curves[pdg];
|
||||||
|
|
||||||
|
if (pd != NULL) {
|
||||||
|
kfree(pd->pd_step);
|
||||||
|
kfree(pd->pd_pwr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
kfree(chinfo[pier].pd_curves);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Convert RF5111 specific data to generic raw data
|
/* Convert RF5111 specific data to generic raw data
|
||||||
* used by interpolation code */
|
* used by interpolation code */
|
||||||
static int
|
static int
|
||||||
|
@ -684,7 +731,7 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
|
|
||||||
if (!chinfo[pier].pd_curves)
|
if (!chinfo[pier].pd_curves)
|
||||||
return -ENOMEM;
|
goto err_out;
|
||||||
|
|
||||||
/* Only one curve for RF5111
|
/* Only one curve for RF5111
|
||||||
* find out which one and place
|
* find out which one and place
|
||||||
|
@ -708,12 +755,12 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode,
|
||||||
pd->pd_step = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111,
|
pd->pd_step = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111,
|
||||||
sizeof(u8), GFP_KERNEL);
|
sizeof(u8), GFP_KERNEL);
|
||||||
if (!pd->pd_step)
|
if (!pd->pd_step)
|
||||||
return -ENOMEM;
|
goto err_out;
|
||||||
|
|
||||||
pd->pd_pwr = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111,
|
pd->pd_pwr = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111,
|
||||||
sizeof(s16), GFP_KERNEL);
|
sizeof(s16), GFP_KERNEL);
|
||||||
if (!pd->pd_pwr)
|
if (!pd->pd_pwr)
|
||||||
return -ENOMEM;
|
goto err_out;
|
||||||
|
|
||||||
/* Fill raw dataset
|
/* Fill raw dataset
|
||||||
* (convert power to 0.25dB units
|
* (convert power to 0.25dB units
|
||||||
|
@ -734,6 +781,10 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err_out:
|
||||||
|
ath5k_eeprom_free_pcal_info(ah, mode);
|
||||||
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse EEPROM data */
|
/* Parse EEPROM data */
|
||||||
|
@ -867,7 +918,7 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
|
|
||||||
if (!chinfo[pier].pd_curves)
|
if (!chinfo[pier].pd_curves)
|
||||||
return -ENOMEM;
|
goto err_out;
|
||||||
|
|
||||||
/* Fill pd_curves */
|
/* Fill pd_curves */
|
||||||
for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
|
for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
|
||||||
|
@ -886,14 +937,13 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode,
|
||||||
sizeof(u8), GFP_KERNEL);
|
sizeof(u8), GFP_KERNEL);
|
||||||
|
|
||||||
if (!pd->pd_step)
|
if (!pd->pd_step)
|
||||||
return -ENOMEM;
|
goto err_out;
|
||||||
|
|
||||||
pd->pd_pwr = kcalloc(pd->pd_points,
|
pd->pd_pwr = kcalloc(pd->pd_points,
|
||||||
sizeof(s16), GFP_KERNEL);
|
sizeof(s16), GFP_KERNEL);
|
||||||
|
|
||||||
if (!pd->pd_pwr)
|
if (!pd->pd_pwr)
|
||||||
return -ENOMEM;
|
goto err_out;
|
||||||
|
|
||||||
|
|
||||||
/* Fill raw dataset
|
/* Fill raw dataset
|
||||||
* (all power levels are in 0.25dB units) */
|
* (all power levels are in 0.25dB units) */
|
||||||
|
@ -925,13 +975,13 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode,
|
||||||
sizeof(u8), GFP_KERNEL);
|
sizeof(u8), GFP_KERNEL);
|
||||||
|
|
||||||
if (!pd->pd_step)
|
if (!pd->pd_step)
|
||||||
return -ENOMEM;
|
goto err_out;
|
||||||
|
|
||||||
pd->pd_pwr = kcalloc(pd->pd_points,
|
pd->pd_pwr = kcalloc(pd->pd_points,
|
||||||
sizeof(s16), GFP_KERNEL);
|
sizeof(s16), GFP_KERNEL);
|
||||||
|
|
||||||
if (!pd->pd_pwr)
|
if (!pd->pd_pwr)
|
||||||
return -ENOMEM;
|
goto err_out;
|
||||||
|
|
||||||
/* Fill raw dataset
|
/* Fill raw dataset
|
||||||
* (all power levels are in 0.25dB units) */
|
* (all power levels are in 0.25dB units) */
|
||||||
|
@ -954,6 +1004,10 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err_out:
|
||||||
|
ath5k_eeprom_free_pcal_info(ah, mode);
|
||||||
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse EEPROM data */
|
/* Parse EEPROM data */
|
||||||
|
@ -1156,7 +1210,7 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
|
|
||||||
if (!chinfo[pier].pd_curves)
|
if (!chinfo[pier].pd_curves)
|
||||||
return -ENOMEM;
|
goto err_out;
|
||||||
|
|
||||||
/* Fill pd_curves */
|
/* Fill pd_curves */
|
||||||
for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
|
for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
|
||||||
|
@ -1177,13 +1231,13 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode,
|
||||||
sizeof(u8), GFP_KERNEL);
|
sizeof(u8), GFP_KERNEL);
|
||||||
|
|
||||||
if (!pd->pd_step)
|
if (!pd->pd_step)
|
||||||
return -ENOMEM;
|
goto err_out;
|
||||||
|
|
||||||
pd->pd_pwr = kcalloc(pd->pd_points,
|
pd->pd_pwr = kcalloc(pd->pd_points,
|
||||||
sizeof(s16), GFP_KERNEL);
|
sizeof(s16), GFP_KERNEL);
|
||||||
|
|
||||||
if (!pd->pd_pwr)
|
if (!pd->pd_pwr)
|
||||||
return -ENOMEM;
|
goto err_out;
|
||||||
|
|
||||||
/* Fill raw dataset
|
/* Fill raw dataset
|
||||||
* convert all pwr levels to
|
* convert all pwr levels to
|
||||||
|
@ -1213,6 +1267,10 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err_out:
|
||||||
|
ath5k_eeprom_free_pcal_info(ah, mode);
|
||||||
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse EEPROM data */
|
/* Parse EEPROM data */
|
||||||
|
@ -1534,53 +1592,6 @@ ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode)
|
|
||||||
{
|
|
||||||
struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
|
|
||||||
struct ath5k_chan_pcal_info *chinfo;
|
|
||||||
u8 pier, pdg;
|
|
||||||
|
|
||||||
switch (mode) {
|
|
||||||
case AR5K_EEPROM_MODE_11A:
|
|
||||||
if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
|
|
||||||
return 0;
|
|
||||||
chinfo = ee->ee_pwr_cal_a;
|
|
||||||
break;
|
|
||||||
case AR5K_EEPROM_MODE_11B:
|
|
||||||
if (!AR5K_EEPROM_HDR_11B(ee->ee_header))
|
|
||||||
return 0;
|
|
||||||
chinfo = ee->ee_pwr_cal_b;
|
|
||||||
break;
|
|
||||||
case AR5K_EEPROM_MODE_11G:
|
|
||||||
if (!AR5K_EEPROM_HDR_11G(ee->ee_header))
|
|
||||||
return 0;
|
|
||||||
chinfo = ee->ee_pwr_cal_g;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
|
|
||||||
if (!chinfo[pier].pd_curves)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
|
|
||||||
struct ath5k_pdgain_info *pd =
|
|
||||||
&chinfo[pier].pd_curves[pdg];
|
|
||||||
|
|
||||||
if (pd != NULL) {
|
|
||||||
kfree(pd->pd_step);
|
|
||||||
kfree(pd->pd_pwr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
kfree(chinfo[pier].pd_curves);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read conformance test limits used for regulatory control */
|
/* Read conformance test limits used for regulatory control */
|
||||||
static int
|
static int
|
||||||
ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah)
|
ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah)
|
||||||
|
|
Loading…
Add table
Reference in a new issue