Commit 80e83da7 authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville

iwlagn: dynamically allocate & reflect calibration data

This makes handling the calibration data more generic
and no longer requires updating IWL_CALIB_MAX when a
new uCode comes with more calibration packets. Since
we just copy the data back, there's also no need for
understanding which calibration we received -- we can
just reflect it back to the runtime uCode.
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarWey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent c27bdc84
...@@ -88,19 +88,18 @@ int iwl_send_calib_results(struct iwl_priv *priv) ...@@ -88,19 +88,18 @@ int iwl_send_calib_results(struct iwl_priv *priv)
.id = REPLY_PHY_CALIBRATION_CMD, .id = REPLY_PHY_CALIBRATION_CMD,
.flags = CMD_SYNC, .flags = CMD_SYNC,
}; };
int i = 0; struct iwl_calib_result *res;
for (i = 0; i < IWL_CALIB_MAX; i++) { list_for_each_entry(res, &priv->calib_results, list) {
int ret; int ret;
if (!priv->calib_results[i].buf) hcmd.len[0] = res->cmd_len;
continue; hcmd.data[0] = &res->hdr;
hcmd.len[0] = priv->calib_results[i].buf_len;
hcmd.data[0] = priv->calib_results[i].buf;
hcmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; hcmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
ret = iwl_trans_send_cmd(trans(priv), &hcmd); ret = iwl_trans_send_cmd(trans(priv), &hcmd);
if (ret) { if (ret) {
IWL_ERR(priv, "Error %d iteration %d\n", ret, i); IWL_ERR(priv, "Error %d on calib cmd %d\n",
ret, res->hdr.op_code);
return ret; return ret;
} }
} }
...@@ -108,28 +107,39 @@ int iwl_send_calib_results(struct iwl_priv *priv) ...@@ -108,28 +107,39 @@ int iwl_send_calib_results(struct iwl_priv *priv)
return 0; return 0;
} }
int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len) int iwl_calib_set(struct iwl_priv *priv,
const struct iwl_calib_hdr *cmd, int len)
{ {
if (res->buf_len != len) { struct iwl_calib_result *res, *tmp;
kfree(res->buf);
res->buf = kzalloc(len, GFP_ATOMIC); res = kmalloc(sizeof(*res) + len - sizeof(struct iwl_calib_hdr),
} GFP_ATOMIC);
if (unlikely(res->buf == NULL)) if (!res)
return -ENOMEM; return -ENOMEM;
memcpy(&res->hdr, cmd, len);
res->cmd_len = len;
list_for_each_entry(tmp, &priv->calib_results, list) {
if (tmp->hdr.op_code == res->hdr.op_code) {
list_replace(&tmp->list, &res->list);
kfree(tmp);
return 0;
}
}
/* wasn't in list already */
list_add_tail(&res->list, &priv->calib_results);
res->buf_len = len;
memcpy(res->buf, buf, len);
return 0; return 0;
} }
void iwl_calib_free_results(struct iwl_priv *priv) void iwl_calib_free_results(struct iwl_priv *priv)
{ {
int i; struct iwl_calib_result *res, *tmp;
for (i = 0; i < IWL_CALIB_MAX; i++) { list_for_each_entry_safe(res, tmp, &priv->calib_results, list) {
kfree(priv->calib_results[i].buf); list_del(&res->list);
priv->calib_results[i].buf = NULL; kfree(res);
priv->calib_results[i].buf_len = 0;
} }
} }
......
...@@ -73,7 +73,8 @@ void iwl_init_sensitivity(struct iwl_priv *priv); ...@@ -73,7 +73,8 @@ void iwl_init_sensitivity(struct iwl_priv *priv);
void iwl_reset_run_time_calib(struct iwl_priv *priv); void iwl_reset_run_time_calib(struct iwl_priv *priv);
int iwl_send_calib_results(struct iwl_priv *priv); int iwl_send_calib_results(struct iwl_priv *priv);
int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len); int iwl_calib_set(struct iwl_priv *priv,
const struct iwl_calib_hdr *cmd, int len);
void iwl_calib_free_results(struct iwl_priv *priv); void iwl_calib_free_results(struct iwl_priv *priv);
#endif /* __iwl_calib_h__ */ #endif /* __iwl_calib_h__ */
...@@ -222,8 +222,7 @@ static int iwlagn_set_Xtal_calib(struct iwl_priv *priv) ...@@ -222,8 +222,7 @@ static int iwlagn_set_Xtal_calib(struct iwl_priv *priv)
iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD); iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD);
cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]); cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]);
cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]); cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]);
return iwl_calib_set(&priv->calib_results[IWL_CALIB_XTAL], return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd));
(u8 *)&cmd, sizeof(cmd));
} }
static int iwlagn_set_temperature_offset_calib(struct iwl_priv *priv) static int iwlagn_set_temperature_offset_calib(struct iwl_priv *priv)
...@@ -240,8 +239,7 @@ static int iwlagn_set_temperature_offset_calib(struct iwl_priv *priv) ...@@ -240,8 +239,7 @@ static int iwlagn_set_temperature_offset_calib(struct iwl_priv *priv)
IWL_DEBUG_CALIB(priv, "Radio sensor offset: %d\n", IWL_DEBUG_CALIB(priv, "Radio sensor offset: %d\n",
le16_to_cpu(cmd.radio_sensor_offset)); le16_to_cpu(cmd.radio_sensor_offset));
return iwl_calib_set(&priv->calib_results[IWL_CALIB_TEMP_OFFSET], return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd));
(u8 *)&cmd, sizeof(cmd));
} }
static int iwlagn_set_temperature_offset_calib_v2(struct iwl_priv *priv) static int iwlagn_set_temperature_offset_calib_v2(struct iwl_priv *priv)
...@@ -276,8 +274,7 @@ static int iwlagn_set_temperature_offset_calib_v2(struct iwl_priv *priv) ...@@ -276,8 +274,7 @@ static int iwlagn_set_temperature_offset_calib_v2(struct iwl_priv *priv)
IWL_DEBUG_CALIB(priv, "Voltage Ref: %d\n", IWL_DEBUG_CALIB(priv, "Voltage Ref: %d\n",
le16_to_cpu(cmd.burntVoltageRef)); le16_to_cpu(cmd.burntVoltageRef));
return iwl_calib_set(&priv->calib_results[IWL_CALIB_TEMP_OFFSET], return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd));
(u8 *)&cmd, sizeof(cmd));
} }
static int iwlagn_send_calib_cfg(struct iwl_priv *priv) static int iwlagn_send_calib_cfg(struct iwl_priv *priv)
...@@ -306,37 +303,14 @@ int iwlagn_rx_calib_result(struct iwl_priv *priv, ...@@ -306,37 +303,14 @@ int iwlagn_rx_calib_result(struct iwl_priv *priv,
struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw; struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw;
int len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; int len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
int index;
/* reduce the size of the length field itself */ /* reduce the size of the length field itself */
len -= 4; len -= 4;
/* Define the order in which the results will be sent to the runtime if (iwl_calib_set(priv, hdr, len))
* uCode. iwl_send_calib_results sends them in a row according to IWL_ERR(priv, "Failed to record calibration data %d\n",
* their index. We sort them here hdr->op_code);
*/
switch (hdr->op_code) {
case IWL_PHY_CALIBRATE_DC_CMD:
index = IWL_CALIB_DC;
break;
case IWL_PHY_CALIBRATE_LO_CMD:
index = IWL_CALIB_LO;
break;
case IWL_PHY_CALIBRATE_TX_IQ_CMD:
index = IWL_CALIB_TX_IQ;
break;
case IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD:
index = IWL_CALIB_TX_IQ_PERD;
break;
case IWL_PHY_CALIBRATE_BASE_BAND_CMD:
index = IWL_CALIB_BASE_BAND;
break;
default:
IWL_ERR(priv, "Unknown calibration notification %d\n",
hdr->op_code);
return -1;
}
iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len);
return 0; return 0;
} }
......
...@@ -1575,6 +1575,8 @@ static int iwl_init_drv(struct iwl_priv *priv) ...@@ -1575,6 +1575,8 @@ static int iwl_init_drv(struct iwl_priv *priv)
mutex_init(&priv->shrd->mutex); mutex_init(&priv->shrd->mutex);
INIT_LIST_HEAD(&priv->calib_results);
priv->ieee_channels = NULL; priv->ieee_channels = NULL;
priv->ieee_rates = NULL; priv->ieee_rates = NULL;
priv->band = IEEE80211_BAND_2GHZ; priv->band = IEEE80211_BAND_2GHZ;
......
...@@ -442,26 +442,12 @@ enum iwlagn_chain_noise_state { ...@@ -442,26 +442,12 @@ enum iwlagn_chain_noise_state {
}; };
/*
* enum iwl_calib
* defines the order in which results of initial calibrations
* should be sent to the runtime uCode
*/
enum iwl_calib {
IWL_CALIB_XTAL,
IWL_CALIB_DC,
IWL_CALIB_LO,
IWL_CALIB_TX_IQ,
IWL_CALIB_TX_IQ_PERD,
IWL_CALIB_BASE_BAND,
IWL_CALIB_TEMP_OFFSET,
IWL_CALIB_MAX
};
/* Opaque calibration results */ /* Opaque calibration results */
struct iwl_calib_result { struct iwl_calib_result {
void *buf; struct list_head list;
size_t buf_len; size_t cmd_len;
struct iwl_calib_hdr hdr;
/* data follows */
}; };
/* Sensitivity calib data */ /* Sensitivity calib data */
...@@ -869,7 +855,7 @@ struct iwl_priv { ...@@ -869,7 +855,7 @@ struct iwl_priv {
s32 last_temperature; s32 last_temperature;
/* init calibration results */ /* init calibration results */
struct iwl_calib_result calib_results[IWL_CALIB_MAX]; struct list_head calib_results;
struct iwl_wipan_noa_data __rcu *noa_data; struct iwl_wipan_noa_data __rcu *noa_data;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment