aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorTomas Winkler <tomas.winkler@intel.com>2008-09-02 23:26:37 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-09-08 14:23:18 -0400
commit6e21f2c109edd746a10e08186484bae8168cdd0c (patch)
treeb006657b3a64edd05fc8b568b4241dc3617ec5d5 /drivers/net
parent7c95168aba66bd11bf9efaf45e16e83ae869401d (diff)
iwlwifi: generic init calibrations framework
This patch allows variable number of init calibrations and allows addition new HW. This patch also fixes critical bug. Only last calibration result was applied. On reception of one calibration result all the calibration was freed. Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000-hw.h7
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c63
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-calib.c60
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c19
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h14
6 files changed, 90 insertions, 81 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
index 17d4f31c5934..c479ee211c5c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
@@ -129,6 +129,13 @@ struct iwl5000_shared {
129 __le32 padding2; 129 __le32 padding2;
130} __attribute__ ((packed)); 130} __attribute__ ((packed));
131 131
132/* calibrations defined for 5000 */
133/* defines the order in which results should be sent to the runtime uCode */
134enum iwl5000_calib {
135 IWL5000_CALIB_LO,
136 IWL5000_CALIB_TX_IQ,
137 IWL5000_CALIB_TX_IQ_PERD,
138};
132 139
133#endif /* __iwl_5000_hw_h__ */ 140#endif /* __iwl_5000_hw_h__ */
134 141
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index cbc01a00eaf4..8b6a72949ac0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -444,48 +444,6 @@ static int iwl5000_send_Xtal_calib(struct iwl_priv *priv)
444 sizeof(cal_cmd), &cal_cmd); 444 sizeof(cal_cmd), &cal_cmd);
445} 445}
446 446
447static int iwl5000_send_calib_results(struct iwl_priv *priv)
448{
449 int ret = 0;
450
451 struct iwl_host_cmd hcmd = {
452 .id = REPLY_PHY_CALIBRATION_CMD,
453 .meta.flags = CMD_SIZE_HUGE,
454 };
455
456 if (priv->calib_results.lo_res) {
457 hcmd.len = priv->calib_results.lo_res_len;
458 hcmd.data = priv->calib_results.lo_res;
459 ret = iwl_send_cmd_sync(priv, &hcmd);
460
461 if (ret)
462 goto err;
463 }
464
465 if (priv->calib_results.tx_iq_res) {
466 hcmd.len = priv->calib_results.tx_iq_res_len;
467 hcmd.data = priv->calib_results.tx_iq_res;
468 ret = iwl_send_cmd_sync(priv, &hcmd);
469
470 if (ret)
471 goto err;
472 }
473
474 if (priv->calib_results.tx_iq_perd_res) {
475 hcmd.len = priv->calib_results.tx_iq_perd_res_len;
476 hcmd.data = priv->calib_results.tx_iq_perd_res;
477 ret = iwl_send_cmd_sync(priv, &hcmd);
478
479 if (ret)
480 goto err;
481 }
482
483 return 0;
484err:
485 IWL_ERROR("Error %d\n", ret);
486 return ret;
487}
488
489static int iwl5000_send_calib_cfg(struct iwl_priv *priv) 447static int iwl5000_send_calib_cfg(struct iwl_priv *priv)
490{ 448{
491 struct iwl5000_calib_cfg_cmd calib_cfg_cmd; 449 struct iwl5000_calib_cfg_cmd calib_cfg_cmd;
@@ -510,33 +468,30 @@ static void iwl5000_rx_calib_result(struct iwl_priv *priv,
510 struct iwl_rx_packet *pkt = (void *)rxb->skb->data; 468 struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
511 struct iwl5000_calib_hdr *hdr = (struct iwl5000_calib_hdr *)pkt->u.raw; 469 struct iwl5000_calib_hdr *hdr = (struct iwl5000_calib_hdr *)pkt->u.raw;
512 int len = le32_to_cpu(pkt->len) & FH_RSCSR_FRAME_SIZE_MSK; 470 int len = le32_to_cpu(pkt->len) & FH_RSCSR_FRAME_SIZE_MSK;
513 471 int index;
514 iwl_free_calib_results(priv);
515 472
516 /* reduce the size of the length field itself */ 473 /* reduce the size of the length field itself */
517 len -= 4; 474 len -= 4;
518 475
476 /* Define the order in which the results will be sent to the runtime
477 * uCode. iwl_send_calib_results sends them in a row according to their
478 * index. We sort them here */
519 switch (hdr->op_code) { 479 switch (hdr->op_code) {
520 case IWL5000_PHY_CALIBRATE_LO_CMD: 480 case IWL5000_PHY_CALIBRATE_LO_CMD:
521 priv->calib_results.lo_res = kzalloc(len, GFP_ATOMIC); 481 index = IWL5000_CALIB_LO;
522 priv->calib_results.lo_res_len = len;
523 memcpy(priv->calib_results.lo_res, pkt->u.raw, len);
524 break; 482 break;
525 case IWL5000_PHY_CALIBRATE_TX_IQ_CMD: 483 case IWL5000_PHY_CALIBRATE_TX_IQ_CMD:
526 priv->calib_results.tx_iq_res = kzalloc(len, GFP_ATOMIC); 484 index = IWL5000_CALIB_TX_IQ;
527 priv->calib_results.tx_iq_res_len = len;
528 memcpy(priv->calib_results.tx_iq_res, pkt->u.raw, len);
529 break; 485 break;
530 case IWL5000_PHY_CALIBRATE_TX_IQ_PERD_CMD: 486 case IWL5000_PHY_CALIBRATE_TX_IQ_PERD_CMD:
531 priv->calib_results.tx_iq_perd_res = kzalloc(len, GFP_ATOMIC); 487 index = IWL5000_CALIB_TX_IQ_PERD;
532 priv->calib_results.tx_iq_perd_res_len = len;
533 memcpy(priv->calib_results.tx_iq_perd_res, pkt->u.raw, len);
534 break; 488 break;
535 default: 489 default:
536 IWL_ERROR("Unknown calibration notification %d\n", 490 IWL_ERROR("Unknown calibration notification %d\n",
537 hdr->op_code); 491 hdr->op_code);
538 return; 492 return;
539 } 493 }
494 iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len);
540} 495}
541 496
542static void iwl5000_rx_calib_complete(struct iwl_priv *priv, 497static void iwl5000_rx_calib_complete(struct iwl_priv *priv,
@@ -834,7 +789,7 @@ static int iwl5000_alive_notify(struct iwl_priv *priv)
834 iwl5000_send_Xtal_calib(priv); 789 iwl5000_send_Xtal_calib(priv);
835 790
836 if (priv->ucode_type == UCODE_RT) 791 if (priv->ucode_type == UCODE_RT)
837 iwl5000_send_calib_results(priv); 792 iwl_send_calib_results(priv);
838 793
839 return 0; 794 return 0;
840} 795}
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c
index ef49440bd7f6..35fb4a4f737d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-calib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-calib.c
@@ -66,6 +66,66 @@
66#include "iwl-core.h" 66#include "iwl-core.h"
67#include "iwl-calib.h" 67#include "iwl-calib.h"
68 68
69/*****************************************************************************
70 * INIT calibrations framework
71 *****************************************************************************/
72
73 int iwl_send_calib_results(struct iwl_priv *priv)
74{
75 int ret = 0;
76 int i = 0;
77
78 struct iwl_host_cmd hcmd = {
79 .id = REPLY_PHY_CALIBRATION_CMD,
80 .meta.flags = CMD_SIZE_HUGE,
81 };
82
83 for (i = 0; i < IWL_CALIB_MAX; i++)
84 if (priv->calib_results[i].buf) {
85 hcmd.len = priv->calib_results[i].buf_len;
86 hcmd.data = priv->calib_results[i].buf;
87 ret = iwl_send_cmd_sync(priv, &hcmd);
88 if (ret)
89 goto err;
90 }
91
92 return 0;
93err:
94 IWL_ERROR("Error %d iteration %d\n", ret, i);
95 return ret;
96}
97EXPORT_SYMBOL(iwl_send_calib_results);
98
99int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len)
100{
101 if (res->buf_len != len) {
102 kfree(res->buf);
103 res->buf = kzalloc(len, GFP_ATOMIC);
104 }
105 if (unlikely(res->buf == NULL))
106 return -ENOMEM;
107
108 res->buf_len = len;
109 memcpy(res->buf, buf, len);
110 return 0;
111}
112EXPORT_SYMBOL(iwl_calib_set);
113
114void iwl_calib_free_results(struct iwl_priv *priv)
115{
116 int i;
117
118 for (i = 0; i < IWL_CALIB_MAX; i++) {
119 kfree(priv->calib_results[i].buf);
120 priv->calib_results[i].buf = NULL;
121 priv->calib_results[i].buf_len = 0;
122 }
123}
124
125/*****************************************************************************
126 * RUNTIME calibrations framework
127 *****************************************************************************/
128
69/* "false alarms" are signals that our DSP tries to lock onto, 129/* "false alarms" are signals that our DSP tries to lock onto,
70 * but then determines that they are either noise, or transmissions 130 * but then determines that they are either noise, or transmissions
71 * from a distant wireless network (also "noise", really) that get 131 * from a distant wireless network (also "noise", really) that get
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 0f9f8b65bf57..1c5406487b11 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -937,22 +937,6 @@ err:
937} 937}
938EXPORT_SYMBOL(iwl_init_drv); 938EXPORT_SYMBOL(iwl_init_drv);
939 939
940void iwl_free_calib_results(struct iwl_priv *priv)
941{
942 kfree(priv->calib_results.lo_res);
943 priv->calib_results.lo_res = NULL;
944 priv->calib_results.lo_res_len = 0;
945
946 kfree(priv->calib_results.tx_iq_res);
947 priv->calib_results.tx_iq_res = NULL;
948 priv->calib_results.tx_iq_res_len = 0;
949
950 kfree(priv->calib_results.tx_iq_perd_res);
951 priv->calib_results.tx_iq_perd_res = NULL;
952 priv->calib_results.tx_iq_perd_res_len = 0;
953}
954EXPORT_SYMBOL(iwl_free_calib_results);
955
956int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) 940int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
957{ 941{
958 int ret = 0; 942 int ret = 0;
@@ -980,10 +964,9 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
980} 964}
981EXPORT_SYMBOL(iwl_set_tx_power); 965EXPORT_SYMBOL(iwl_set_tx_power);
982 966
983
984void iwl_uninit_drv(struct iwl_priv *priv) 967void iwl_uninit_drv(struct iwl_priv *priv)
985{ 968{
986 iwl_free_calib_results(priv); 969 iwl_calib_free_results(priv);
987 iwlcore_free_geos(priv); 970 iwlcore_free_geos(priv);
988 iwl_free_channel_map(priv); 971 iwl_free_channel_map(priv);
989 kfree(priv->scan); 972 kfree(priv->scan);
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index ff86abc668ba..b5db050b22d1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -186,7 +186,6 @@ struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg,
186void iwl_hw_detect(struct iwl_priv *priv); 186void iwl_hw_detect(struct iwl_priv *priv);
187 187
188void iwl_clear_stations_table(struct iwl_priv *priv); 188void iwl_clear_stations_table(struct iwl_priv *priv);
189void iwl_free_calib_results(struct iwl_priv *priv);
190void iwl_reset_qos(struct iwl_priv *priv); 189void iwl_reset_qos(struct iwl_priv *priv);
191void iwl_set_rxon_chain(struct iwl_priv *priv); 190void iwl_set_rxon_chain(struct iwl_priv *priv);
192int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch); 191int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch);
@@ -289,6 +288,13 @@ int iwl_scan_initiate(struct iwl_priv *priv);
289void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); 288void iwl_setup_rx_scan_handlers(struct iwl_priv *priv);
290void iwl_setup_scan_deferred_work(struct iwl_priv *priv); 289void iwl_setup_scan_deferred_work(struct iwl_priv *priv);
291 290
291/*******************************************************************************
292 * Calibrations - implemented in iwl-calib.c
293 ******************************************************************************/
294int iwl_send_calib_results(struct iwl_priv *priv);
295int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len);
296void iwl_calib_free_results(struct iwl_priv *priv);
297
292/***************************************************** 298/*****************************************************
293 * S e n d i n g H o s t C o m m a n d s * 299 * S e n d i n g H o s t C o m m a n d s *
294 *****************************************************/ 300 *****************************************************/
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 0711b35b9ade..5a55c876917d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -728,13 +728,10 @@ struct statistics_general_data {
728 u32 beacon_energy_c; 728 u32 beacon_energy_c;
729}; 729};
730 730
731struct iwl_calib_results { 731/* Opaque calibration results */
732 void *tx_iq_res; 732struct iwl_calib_result {
733 void *tx_iq_perd_res; 733 void *buf;
734 void *lo_res; 734 size_t buf_len;
735 u32 tx_iq_res_len;
736 u32 tx_iq_perd_res_len;
737 u32 lo_res_len;
738}; 735};
739 736
740enum ucode_type { 737enum ucode_type {
@@ -796,6 +793,7 @@ enum {
796 793
797 794
798#define IWL_MAX_NUM_QUEUES 20 /* FIXME: do dynamic allocation */ 795#define IWL_MAX_NUM_QUEUES 20 /* FIXME: do dynamic allocation */
796#define IWL_CALIB_MAX 3
799 797
800struct iwl_priv { 798struct iwl_priv {
801 799
@@ -839,7 +837,7 @@ struct iwl_priv {
839 s32 last_temperature; 837 s32 last_temperature;
840 838
841 /* init calibration results */ 839 /* init calibration results */
842 struct iwl_calib_results calib_results; 840 struct iwl_calib_result calib_results[IWL_CALIB_MAX];
843 841
844 /* Scan related variables */ 842 /* Scan related variables */
845 unsigned long last_scan_jiffies; 843 unsigned long last_scan_jiffies;