summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-11-17 08:51:57 -0800
committerWey-Yi Guy <wey-yi.w.guy@intel.com>2011-11-25 10:49:10 -0800
commitf02c2fd383f4c771c75daf391abdbdcb88848439 (patch)
treec0538e4f20d339fd67685d0af50c3200bc58897b /drivers/net/wireless/iwlwifi/iwl-agn-calib.c
parent93b64105e5642728cfc441e20a42164323fe4ad0 (diff)
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: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-calib.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-calib.c50
1 files changed, 30 insertions, 20 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
index c7bcafabb3b..4d021059495 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
@@ -88,19 +88,18 @@ int iwl_send_calib_results(struct iwl_priv *priv)
.id = REPLY_PHY_CALIBRATION_CMD,
.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;
- if (!priv->calib_results[i].buf)
- continue;
- hcmd.len[0] = priv->calib_results[i].buf_len;
- hcmd.data[0] = priv->calib_results[i].buf;
+ hcmd.len[0] = res->cmd_len;
+ hcmd.data[0] = &res->hdr;
hcmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
ret = iwl_trans_send_cmd(trans(priv), &hcmd);
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;
}
}
@@ -108,28 +107,39 @@ int iwl_send_calib_results(struct iwl_priv *priv)
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) {
- kfree(res->buf);
- res->buf = kzalloc(len, GFP_ATOMIC);
- }
- if (unlikely(res->buf == NULL))
+ struct iwl_calib_result *res, *tmp;
+
+ res = kmalloc(sizeof(*res) + len - sizeof(struct iwl_calib_hdr),
+ GFP_ATOMIC);
+ if (!res)
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;
}
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++) {
- kfree(priv->calib_results[i].buf);
- priv->calib_results[i].buf = NULL;
- priv->calib_results[i].buf_len = 0;
+ list_for_each_entry_safe(res, tmp, &priv->calib_results, list) {
+ list_del(&res->list);
+ kfree(res);
}
}